mirror of
https://github.com/koel/koel
synced 2024-11-10 06:34:14 +00:00
feat (test): add YouTubeVideoItem component tests
This commit is contained in:
parent
621c869a82
commit
c73122fe5a
4 changed files with 104 additions and 43 deletions
44
resources/assets/js/components/ui/YouTubeVideoItem.spec.ts
Normal file
44
resources/assets/js/components/ui/YouTubeVideoItem.spec.ts
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import { expect, it } from 'vitest'
|
||||||
|
import ComponentTestCase from '@/__tests__/ComponentTestCase'
|
||||||
|
import YouTubeVideoItem from './YouTubeVideoItem.vue'
|
||||||
|
import { fireEvent } from '@testing-library/vue'
|
||||||
|
import { youTubeService } from '@/services'
|
||||||
|
|
||||||
|
let video: YouTubeVideo
|
||||||
|
|
||||||
|
new class extends ComponentTestCase {
|
||||||
|
private renderComponent () {
|
||||||
|
video = {
|
||||||
|
id: {
|
||||||
|
videoId: 'cLgJQ8Zj3AA'
|
||||||
|
},
|
||||||
|
snippet: {
|
||||||
|
title: 'Guess what it is',
|
||||||
|
description: 'From the LA Opening Gala 2014: John Williams Celebration',
|
||||||
|
thumbnails: {
|
||||||
|
default: {
|
||||||
|
url: 'https://i.ytimg.com/an_webp/cLgJQ8Zj3AA/mqdefault_6s.webp'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.render(YouTubeVideoItem, {
|
||||||
|
props: {
|
||||||
|
video
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
protected test () {
|
||||||
|
it('renders', () => expect(this.renderComponent().html()).toMatchSnapshot())
|
||||||
|
|
||||||
|
it('plays', async () => {
|
||||||
|
const mock = this.mock(youTubeService, 'play')
|
||||||
|
const { getByRole } = this.renderComponent()
|
||||||
|
|
||||||
|
await fireEvent.click(getByRole('button'))
|
||||||
|
|
||||||
|
expect(mock).toHaveBeenCalledWith(video)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
46
resources/assets/js/components/ui/YouTubeVideoItem.vue
Normal file
46
resources/assets/js/components/ui/YouTubeVideoItem.vue
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<template>
|
||||||
|
<a :href="url" data-testid="youtube-search-result" role="button" @click.prevent="play">
|
||||||
|
<img :alt="video.snippet.title" :src="video.snippet.thumbnails.default.url" width="90">
|
||||||
|
<div class="meta">
|
||||||
|
<h3 class="title">{{ video.snippet.title }}</h3>
|
||||||
|
<p class="desc">{{ video.snippet.description }}</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, toRefs } from 'vue'
|
||||||
|
import { youTubeService } from '@/services'
|
||||||
|
|
||||||
|
const props = defineProps<{ video: YouTubeVideo }>()
|
||||||
|
const { video } = toRefs(props)
|
||||||
|
|
||||||
|
const url = computed(() => `https://youtu.be/${video.value.id.videoId}`)
|
||||||
|
|
||||||
|
const play = () => youTubeService.play(video.value)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
a {
|
||||||
|
display: flex;
|
||||||
|
padding: 12px 0;
|
||||||
|
|
||||||
|
&:hover, &:active, &:focus {
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
margin-bottom: .4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desc {
|
||||||
|
font-size: .9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
margin-right: 10px;
|
||||||
|
align-self: self-start;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,23 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="youtube-extra-wrapper">
|
<div class="youtube-extra-wrapper">
|
||||||
<template v-if="videos.length">
|
<template v-if="videos.length">
|
||||||
<a
|
<YouTubeVideo v-for="video in videos" :key="video.id.videoId" :video="video"/>
|
||||||
v-for="video in videos"
|
|
||||||
:key="video.id.videoId"
|
|
||||||
:href="`https://youtu.be/${video.id.videoId}`"
|
|
||||||
class="video"
|
|
||||||
data-testid="youtube-search-result"
|
|
||||||
role="button"
|
|
||||||
@click.prevent="play(video)"
|
|
||||||
>
|
|
||||||
<div class="thumb">
|
|
||||||
<img :alt="video.snippet.title" :src="video.snippet.thumbnails.default.url" width="90">
|
|
||||||
</div>
|
|
||||||
<div class="meta">
|
|
||||||
<h3 class="title">{{ video.snippet.title }}</h3>
|
|
||||||
<p class="desc">{{ video.snippet.description }}</p>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<Btn v-if="!loading" class="more" data-testid="youtube-search-more-btn" @click.prevent="loadMore">Load More</Btn>
|
<Btn v-if="!loading" class="more" data-testid="youtube-search-more-btn" @click.prevent="loadMore">Load More</Btn>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -31,6 +15,7 @@ import { defineAsyncComponent, ref, toRefs, watchEffect } from 'vue'
|
||||||
import { youTubeService } from '@/services'
|
import { youTubeService } from '@/services'
|
||||||
|
|
||||||
const Btn = defineAsyncComponent(() => import('@/components/ui/Btn.vue'))
|
const Btn = defineAsyncComponent(() => import('@/components/ui/Btn.vue'))
|
||||||
|
const YouTubeVideo = defineAsyncComponent(() => import('@/components/ui/YouTubeVideoItem.vue'))
|
||||||
|
|
||||||
const props = defineProps<{ song: Song }>()
|
const props = defineProps<{ song: Song }>()
|
||||||
const { song } = toRefs(props)
|
const { song } = toRefs(props)
|
||||||
|
@ -40,8 +25,6 @@ const videos = ref<YouTubeVideo[]>([])
|
||||||
|
|
||||||
watchEffect(() => (videos.value = song.value.youtube?.items || []))
|
watchEffect(() => (videos.value = song.value.youtube?.items || []))
|
||||||
|
|
||||||
const play = (video: YouTubeVideo) => youTubeService.play(video)
|
|
||||||
|
|
||||||
const loadMore = async () => {
|
const loadMore = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
|
||||||
|
@ -63,30 +46,8 @@ const loadMore = async () => {
|
||||||
.youtube-extra-wrapper {
|
.youtube-extra-wrapper {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
|
||||||
.video {
|
a:last-of-type {
|
||||||
display: flex;
|
margin-bottom: 16px;
|
||||||
padding: 12px 0;
|
|
||||||
|
|
||||||
.thumb {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 1.1rem;
|
|
||||||
margin-bottom: .4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.desc {
|
|
||||||
font-size: .9rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover, &:active, &:focus {
|
|
||||||
color: var(--color-text-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-of-type {
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
|
exports[`renders 1`] = `
|
||||||
|
<a href="https://youtu.be/cLgJQ8Zj3AA" data-testid="youtube-search-result" role="button" data-v-da3db7c2=""><img alt="Guess what it is" src="https://i.ytimg.com/an_webp/cLgJQ8Zj3AA/mqdefault_6s.webp" width="90" data-v-da3db7c2="" />
|
||||||
|
<div class="meta" data-v-da3db7c2="">
|
||||||
|
<h3 class="title" data-v-da3db7c2="">Guess what it is</h3>
|
||||||
|
<p class="desc" data-v-da3db7c2="">From the LA Opening Gala 2014: John Williams Celebration</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
`;
|
Loading…
Reference in a new issue