mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-05 23:56:42 +08:00
fix: 修正下载器卡片属性透传 (#714)
This commit is contained in:
@@ -1,8 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
defineOptions({ inheritAttrs: false })
|
||||||
|
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import { formatFileSize } from '@/@core/utils/formatters'
|
import { formatFileSize } from '@/@core/utils/formatters'
|
||||||
import type { DownloaderConf, DownloaderInfo } from '@/api/types'
|
import type { DownloaderConf, DownloaderInfo } from '@/api/types'
|
||||||
import { getLogoUrl } from '@/utils/imageUtils'
|
import { getLogoUrl } from '@/utils/imageUtils'
|
||||||
|
import { mergeProps } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { downloaderDict } from '@/api/constants'
|
import { downloaderDict } from '@/api/constants'
|
||||||
import { useBackground } from '@/composables/useBackground'
|
import { useBackground } from '@/composables/useBackground'
|
||||||
@@ -122,7 +125,7 @@ onUnmounted(() => {
|
|||||||
<template>
|
<template>
|
||||||
<VHover v-slot="hover">
|
<VHover v-slot="hover">
|
||||||
<VCard
|
<VCard
|
||||||
v-bind="hover.props"
|
v-bind="mergeProps($attrs, hover.props)"
|
||||||
variant="tonal"
|
variant="tonal"
|
||||||
class="app-card-shell app-card-colorful"
|
class="app-card-shell app-card-colorful"
|
||||||
:style="{ '--app-card-accent-rgb': accentRgb }"
|
:style="{ '--app-card-accent-rgb': accentRgb }"
|
||||||
@@ -146,7 +149,10 @@ onUnmounted(() => {
|
|||||||
/>
|
/>
|
||||||
<span class="app-card-summary__title text-h6">{{ downloader.name }}</span>
|
<span class="app-card-summary__title text-h6">{{ downloader.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="downloaderDict[downloader.type] && props.downloader.enabled" class="app-card-summary__meta text-sm">
|
<div
|
||||||
|
v-if="downloaderDict[downloader.type] && props.downloader.enabled"
|
||||||
|
class="app-card-summary__meta text-sm"
|
||||||
|
>
|
||||||
<span class="app-card-summary__meta-item">{{ `↑ ${formatFileSize(upload_rate, 1)}/s` }}</span>
|
<span class="app-card-summary__meta-item">{{ `↑ ${formatFileSize(upload_rate, 1)}/s` }}</span>
|
||||||
<span class="app-card-summary__meta-item">{{ `↓ ${formatFileSize(download_rate, 1)}/s` }}</span>
|
<span class="app-card-summary__meta-item">{{ `↓ ${formatFileSize(download_rate, 1)}/s` }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
import DownloaderCard from '@/components/cards/DownloaderCard.vue'
|
||||||
|
import { renderWithProviders } from '@tests/support/render'
|
||||||
|
import { defineComponent, h, ref } from 'vue'
|
||||||
|
import { describe, expect, it, vi } from 'vitest'
|
||||||
|
|
||||||
|
vi.mock('@/api', () => ({
|
||||||
|
default: {
|
||||||
|
get: vi.fn(),
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|
||||||
|
vi.mock('@/composables/useBackground', () => ({
|
||||||
|
useBackground: () => ({
|
||||||
|
useConditionalDataRefresh: () => ({ stop: vi.fn() }),
|
||||||
|
}),
|
||||||
|
}))
|
||||||
|
|
||||||
|
vi.mock('@/composables/useCardAccentColor', () => ({
|
||||||
|
useCardAccentColor: () => ({
|
||||||
|
accentRgb: ref('141, 81, 249'),
|
||||||
|
imageRef: ref(),
|
||||||
|
updateAccentColor: vi.fn(),
|
||||||
|
}),
|
||||||
|
}))
|
||||||
|
|
||||||
|
vi.mock('@/utils/imageUtils', () => ({
|
||||||
|
getLogoUrl: () => '/downloader.png',
|
||||||
|
}))
|
||||||
|
|
||||||
|
const passthroughStub = (name: string, tag = 'div') =>
|
||||||
|
defineComponent({
|
||||||
|
name,
|
||||||
|
inheritAttrs: false,
|
||||||
|
setup(_props, { attrs, slots }) {
|
||||||
|
return () => h(tag, attrs, slots.default?.())
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const VHoverStub = defineComponent({
|
||||||
|
name: 'VHover',
|
||||||
|
inheritAttrs: false,
|
||||||
|
setup(_props, { slots }) {
|
||||||
|
return () => slots.default?.({ props: { onMouseenter: hoverMouseenter } })
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const hoverMouseenter = vi.fn()
|
||||||
|
|
||||||
|
const VCardStub = passthroughStub('VCard', 'article')
|
||||||
|
|
||||||
|
const globalStubs = {
|
||||||
|
IconBtn: passthroughStub('IconBtn', 'button'),
|
||||||
|
VBadge: passthroughStub('VBadge', 'span'),
|
||||||
|
VCard: VCardStub,
|
||||||
|
VCardText: passthroughStub('VCardText'),
|
||||||
|
VDialogCloseBtn: passthroughStub('VDialogCloseBtn', 'button'),
|
||||||
|
VHover: VHoverStub,
|
||||||
|
VIcon: passthroughStub('VIcon', 'span'),
|
||||||
|
VImg: defineComponent({
|
||||||
|
name: 'VImg',
|
||||||
|
props: { src: String },
|
||||||
|
setup(props, { attrs }) {
|
||||||
|
return () => h('img', { ...attrs, src: props.src })
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
const downloader = {
|
||||||
|
name: 'qb-main',
|
||||||
|
type: 'qbittorrent',
|
||||||
|
default: true,
|
||||||
|
enabled: false,
|
||||||
|
config: {},
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('DownloaderCard', () => {
|
||||||
|
it('places draggable attributes on the card DOM instead of the hover wrapper', async () => {
|
||||||
|
const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
||||||
|
const externalMouseenter = vi.fn()
|
||||||
|
hoverMouseenter.mockClear()
|
||||||
|
const Harness = defineComponent({
|
||||||
|
setup() {
|
||||||
|
return () =>
|
||||||
|
h(DownloaderCard, {
|
||||||
|
downloader,
|
||||||
|
downloaders: [downloader],
|
||||||
|
allowRefresh: false,
|
||||||
|
'data-draggable': 'true',
|
||||||
|
'aria-label': 'qb-main-card',
|
||||||
|
class: 'draggable-item',
|
||||||
|
onMouseenter: externalMouseenter,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const { container } = await renderWithProviders(Harness, {
|
||||||
|
global: { stubs: globalStubs },
|
||||||
|
})
|
||||||
|
|
||||||
|
const card = container.querySelector('article')
|
||||||
|
expect(card).toBeInTheDocument()
|
||||||
|
expect(card).toHaveAttribute('data-draggable', 'true')
|
||||||
|
expect(card).toHaveAttribute('aria-label', 'qb-main-card')
|
||||||
|
expect(card).toHaveClass('draggable-item', 'app-card-shell', 'app-card-colorful')
|
||||||
|
expect(container.querySelectorAll('[data-draggable]')).toHaveLength(1)
|
||||||
|
card?.dispatchEvent(new MouseEvent('mouseenter'))
|
||||||
|
expect(externalMouseenter).toHaveBeenCalledOnce()
|
||||||
|
expect(hoverMouseenter).toHaveBeenCalledOnce()
|
||||||
|
|
||||||
|
const attributeWarnings = warn.mock.calls.filter(([message]) =>
|
||||||
|
String(message).includes('Extraneous non-props attributes'),
|
||||||
|
)
|
||||||
|
expect(attributeWarnings).toHaveLength(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user