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>
|
||||
<div class="youtube-extra-wrapper">
|
||||
<template v-if="videos.length">
|
||||
<a
|
||||
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>
|
||||
<YouTubeVideo v-for="video in videos" :key="video.id.videoId" :video="video"/>
|
||||
<Btn v-if="!loading" class="more" data-testid="youtube-search-more-btn" @click.prevent="loadMore">Load More</Btn>
|
||||
</template>
|
||||
|
||||
|
@ -31,6 +15,7 @@ import { defineAsyncComponent, ref, toRefs, watchEffect } from 'vue'
|
|||
import { youTubeService } from '@/services'
|
||||
|
||||
const Btn = defineAsyncComponent(() => import('@/components/ui/Btn.vue'))
|
||||
const YouTubeVideo = defineAsyncComponent(() => import('@/components/ui/YouTubeVideoItem.vue'))
|
||||
|
||||
const props = defineProps<{ song: Song }>()
|
||||
const { song } = toRefs(props)
|
||||
|
@ -40,8 +25,6 @@ const videos = ref<YouTubeVideo[]>([])
|
|||
|
||||
watchEffect(() => (videos.value = song.value.youtube?.items || []))
|
||||
|
||||
const play = (video: YouTubeVideo) => youTubeService.play(video)
|
||||
|
||||
const loadMore = async () => {
|
||||
loading.value = true
|
||||
|
||||
|
@ -63,30 +46,8 @@ const loadMore = async () => {
|
|||
.youtube-extra-wrapper {
|
||||
overflow-x: hidden;
|
||||
|
||||
.video {
|
||||
display: flex;
|
||||
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;
|
||||
}
|
||||
a:last-of-type {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
</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