From 254233973386dc1291431dcd84cc5659eb0965ce Mon Sep 17 00:00:00 2001 From: InfinityPacer <160988576+InfinityPacer@users.noreply.github.com> Date: Sun, 19 Jul 2026 17:05:56 +0800 Subject: [PATCH] test(site): cover site resource dialog (#563) --- eslint-suppressions.json | 5 - src/components/dialog/SiteResourceDialog.vue | 62 ++- .../__tests__/SiteResourceDialog.spec.ts | 428 ++++++++++++++++++ src/locales/en-US.ts | 1 + src/locales/zh-CN.ts | 1 + src/locales/zh-TW.ts | 1 + tests/support/factories/site.ts | 38 +- tests/support/msw/handlers/site.ts | 36 +- vite.config.ts | 7 + 9 files changed, 558 insertions(+), 21 deletions(-) create mode 100644 src/components/dialog/__tests__/SiteResourceDialog.spec.ts diff --git a/eslint-suppressions.json b/eslint-suppressions.json index b298a520..ac4fc243 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -380,11 +380,6 @@ "count": 1 } }, - "src/components/dialog/SiteResourceDialog.vue": { - "@typescript-eslint/no-unused-vars": { - "count": 2 - } - }, "src/components/dialog/SiteStatisticsDialog.vue": { "@typescript-eslint/no-explicit-any": { "count": 1 diff --git a/src/components/dialog/SiteResourceDialog.vue b/src/components/dialog/SiteResourceDialog.vue index dde8cfb2..2cd7d27b 100644 --- a/src/components/dialog/SiteResourceDialog.vue +++ b/src/components/dialog/SiteResourceDialog.vue @@ -45,6 +45,11 @@ const resourcePage = ref(1) // 加载状态 const resourceLoading = ref(false) +const resourceError = ref(false) + +// 只有最后发起的搜索可以更新资源数据、请求状态和移动端搜索面板。 +let resourceRequestId = 0 + // 移动端搜索栏是否展开 const mobileSearchExpanded = ref(false) @@ -134,35 +139,46 @@ async function addDownload(_torrent: TorrentInfo) { } // 添加下载成功 -function addDownloadSuccess(_url: string) { +function addDownloadSuccess() { addDownloadDialog.value = false } // 添加下载失败 -function addDownloadError(_error: string) { +function addDownloadError() { addDownloadDialog.value = false } // 调用API,查询站点资源 async function getResourceList() { + const requestId = ++resourceRequestId resourceLoading.value = true + resourceError.value = false resourcePage.value = 1 try { - resourceDataList.value = await api.get(`site/resource/${props.site?.id}`, { + const resources: TorrentInfo[] = await api.get(`site/resource/${props.site?.id}`, { params: { keyword: keyword.value, cat: selectCategory.value?.join(','), }, }) + + if (requestId === resourceRequestId) { + resourceDataList.value = resources + } } catch (error) { - console.error(error) - } + if (requestId === resourceRequestId) { + console.error(error) + resourceError.value = true + } + } finally { + if (requestId === resourceRequestId) { + resourceLoading.value = false - resourceLoading.value = false - - if (isMobileLayout.value) { - mobileSearchExpanded.value = false + if (isMobileLayout.value) { + mobileSearchExpanded.value = false + } + } } } @@ -280,10 +296,7 @@ onMounted(() => { -
+
{{ resultSummaryText }}
@@ -350,7 +363,14 @@ onMounted(() => { /> - + {{ t('dialog.siteResource.search') }} @@ -366,6 +386,20 @@ onMounted(() => {
+ + + + + {{ torrent?.title }} + + + + + `, +}) + +const DialogStub = defineComponent({ + name: 'VDialog', + template: '
', +}) + +const ProgressiveCardGridStub = defineComponent({ + name: 'ProgressiveCardGrid', + props: { + getItemKey: { type: Function as PropType<(item: TorrentInfo, index: number) => string>, required: true }, + items: { type: Array as PropType, required: true }, + }, + setup(props, { slots }) { + return () => + h( + 'section', + { 'data-testid': 'progressive-grid' }, + props.items.map((item, index) => + h('article', { 'data-resource-key': props.getItemKey(item, index) }, slots.default?.({ item })), + ), + ) + }, +}) + +const DataTableStub = defineComponent({ + name: 'VDataTable', + props: { + items: { type: Array as PropType, required: true }, + itemsPerPage: { type: Number, required: true }, + loading: Boolean, + page: { type: Number, required: true }, + }, + emits: ['update:itemsPerPage', 'update:page'], + setup(props, { emit, slots }) { + return () => + h('section', { 'data-loading': String(props.loading), 'data-testid': 'resource-table' }, [ + h('span', { 'data-testid': 'resource-page' }, String(props.page)), + h('button', { onClick: () => emit('update:page', 4), type: 'button' }, 'page-4'), + h('button', { onClick: () => emit('update:itemsPerPage', 100), type: 'button' }, 'per-page-100'), + ...props.items.flatMap(item => slots['item.title']?.({ item }) ?? []), + props.items.length === 0 ? slots['no-data']?.({}) : null, + ]) + }, +}) + +function createDeferred() { + let resolve!: (value: T) => void + const promise = new Promise(done => { + resolve = done + }) + return { promise, resolve } +} + +function setViewport(width: number) { + Object.defineProperty(window, 'innerWidth', { configurable: true, value: width, writable: true }) + window.dispatchEvent(new Event('resize')) +} + +async function renderDialog( + site = createSite({ id: 501, name: '资源测试站' }), + stubs: Record = {}, +) { + const close = vi.fn() + const result = await renderWithProviders(SiteResourceDialog, { + props: { site, onClose: close }, + global: { + stubs: { + AddDownloadDialog: AddDownloadDialogStub, + ProgressiveCardGrid: ProgressiveCardGridStub, + VDialog: DialogStub, + ...stubs, + }, + }, + }) + + return { ...result, close, site } +} + +describe('SiteResourceDialog', () => { + beforeEach(() => { + vi.spyOn(console, 'error').mockImplementation(() => {}) + vi.spyOn(console, 'warn').mockImplementation(() => {}) + setViewport(1280) + }) + + it.each([ + ['success', 200], + ['HTTP failure', 500], + ] as const)('keeps the newest mobile search state when an older request ends with %s', async (_case, oldStatus) => { + setViewport(390) + const oldResponse = createDeferred() + const latestResponse = createDeferred() + const oldRequested = vi.fn() + const latestRequested = vi.fn() + const latestResource = createTorrentInfo({ title: '新条件结果' }) + server.use( + siteCategoriesHandler(501, [createSiteCategory()]), + http.get(siteApiUrls.resources(501), async ({ request }) => { + const keyword = new URL(request.url).searchParams.get('keyword') + if (keyword) { + latestRequested() + return HttpResponse.json(await latestResponse.promise) + } + + oldRequested() + await oldResponse.promise + return oldStatus === 200 + ? HttpResponse.json([createTorrentInfo({ title: '旧条件结果' })]) + : HttpResponse.json({ detail: 'stale failure' }, { status: oldStatus }) + }), + ) + const user = userEvent.setup() + + const { container } = await renderDialog() + await waitFor(() => expect(oldRequested).toHaveBeenCalledOnce()) + await user.click(container.querySelector('.site-resource-mobile-search__toggle') as HTMLElement) + const keywordFields = screen.getAllByLabelText('搜索关键字') + const keyword = keywordFields[keywordFields.length - 1] + await user.type(keyword, 'new') + const searchButtons = screen.getAllByRole('button', { name: /搜索/ }) + await user.click(searchButtons[searchButtons.length - 1]) + await waitFor(() => expect(latestRequested).toHaveBeenCalledOnce()) + await waitFor(() => expect(getActiveRequestsCount()).toBe(2)) + + oldResponse.resolve() + await waitFor(() => expect(getActiveRequestsCount()).toBe(1)) + expect(screen.getByText('加载中...')).toBeInTheDocument() + expect(container.querySelector('.site-resource-filter-panel')).toBeInTheDocument() + expect(screen.queryByText('资源加载失败,请重试')).not.toBeInTheDocument() + if (oldStatus === 500) expect(console.error).not.toHaveBeenCalled() + + latestResponse.resolve([latestResource]) + expect(await screen.findByText('新条件结果')).toBeInTheDocument() + await waitFor(() => expect(getActiveRequestsCount()).toBe(0)) + + expect(screen.queryByText('旧条件结果')).not.toBeInTheDocument() + expect(screen.queryByText('加载中...')).not.toBeInTheDocument() + expect(screen.queryByLabelText('搜索关键字')).not.toBeInTheDocument() + expect(screen.queryByText('资源加载失败,请重试')).not.toBeInTheDocument() + }) + + it('shows a retry action after resource loading fails and recovers on the same query', async () => { + let attempts = 0 + server.use( + siteCategoriesHandler(501, []), + http.get(siteApiUrls.resources(501), () => { + attempts += 1 + if (attempts === 1) return HttpResponse.json({ detail: 'temporary failure' }, { status: 500 }) + + return HttpResponse.json([createTorrentInfo({ title: '重试恢复结果' })]) + }), + ) + const user = userEvent.setup() + + await renderDialog() + + await user.click(await screen.findByRole('button', { name: '重试' })) + expect(await screen.findByText('重试恢复结果')).toBeInTheDocument() + expect(attempts).toBe(2) + }) + + it('loads categories and resources from their direct-array endpoints', async () => { + const categoryRequests: URL[] = [] + const resourceRequests: URL[] = [] + server.use( + siteCategoriesHandler(501, [createSiteCategory({ desc: '高清电影', id: 11 })], 200, url => + categoryRequests.push(url), + ), + siteResourcesHandler(501, [createTorrentInfo({ title: '首载资源' })], 200, url => resourceRequests.push(url)), + ) + + await renderDialog() + + expect(await screen.findByText('首载资源')).toBeInTheDocument() + expect(categoryRequests).toHaveLength(1) + expect(resourceRequests).toHaveLength(1) + expect(resourceRequests[0].searchParams.get('keyword')).toBeNull() + expect(resourceRequests[0].searchParams.get('cat')).toBe('') + }) + + it('sends the exact keyword and selected category ids on every search', async () => { + const requests: URL[] = [] + server.use( + siteCategoriesHandler(501, [ + createSiteCategory({ desc: '电影', id: 11 }), + createSiteCategory({ cat: 'tv', desc: '剧集', id: 22 }), + ]), + siteResourcesHandler(501, [], 200, url => requests.push(url)), + ) + const user = userEvent.setup() + + await renderDialog() + await waitFor(() => expect(requests).toHaveLength(1)) + await user.type(screen.getByLabelText('搜索关键字'), '2160p') + await user.click(screen.getByLabelText('资源分类')) + await user.click(await screen.findByRole('option', { name: '电影' })) + await user.click(await screen.findByRole('option', { name: '剧集' })) + await user.click(screen.getByRole('button', { name: /搜索/ })) + + await waitFor(() => expect(requests).toHaveLength(2)) + expect(requests[1].searchParams.get('keyword')).toBe('2160p') + expect(requests[1].searchParams.get('cat')).toBe('11,22') + }) + + it('distinguishes a valid empty resource list from a category request failure', async () => { + server.use(siteCategoriesHandler(501, [], 500), siteResourcesHandler(501, [])) + + await renderDialog() + + expect(await screen.findByText('没有数据')).toBeInTheDocument() + expect(screen.queryByText('资源加载失败,请重试')).not.toBeInTheDocument() + await waitFor(() => expect(console.error).toHaveBeenCalledOnce()) + }) + + it('exposes loading during a repeated search and clears it when the latest request completes', async () => { + const nextResponse = createDeferred() + let requestCount = 0 + server.use( + siteCategoriesHandler(501, []), + http.get(siteApiUrls.resources(501), async () => { + requestCount += 1 + if (requestCount === 1) return HttpResponse.json([]) + return HttpResponse.json(await nextResponse.promise) + }), + ) + const user = userEvent.setup() + + await renderDialog(undefined, { VDataTable: DataTableStub }) + await waitFor(() => expect(screen.getByTestId('resource-table')).toHaveAttribute('data-loading', 'false')) + await user.click(screen.getByRole('button', { name: /搜索/ })) + await waitFor(() => expect(screen.getByTestId('resource-table')).toHaveAttribute('data-loading', 'true')) + nextResponse.resolve([createTorrentInfo({ title: '重复搜索结果' })]) + + expect(await screen.findByText('重复搜索结果')).toBeInTheDocument() + expect(screen.getByTestId('resource-table')).toHaveAttribute('data-loading', 'false') + }) + + it('renders resource metadata and every promotion style branch', async () => { + server.use( + siteCategoriesHandler(501, []), + siteResourcesHandler(501, [ + createTorrentInfo({ + date_elapsed: '2 小时前', + description: '完整资源说明', + downloadvolumefactor: 0, + freedate_diff: '剩余 1 天', + hit_and_run: true, + labels: ['原盘'], + pubdate: '2026-07-19', + title: '免费资源', + volume_factor: 'FREE', + }), + createTorrentInfo({ downloadvolumefactor: 0.5, title: '半价资源', volume_factor: '50%' }), + createTorrentInfo({ title: '双倍上传', uploadvolumefactor: 2, volume_factor: '2X' }), + createTorrentInfo({ title: '普通资源' }), + ]), + ) + + await renderDialog() + + expect(await screen.findByText('免费资源')).toBeInTheDocument() + expect(screen.getByText('完整资源说明')).toBeInTheDocument() + expect(screen.getByText('H&R')).toBeInTheDocument() + expect(screen.getByText('剩余 1 天')).toBeInTheDocument() + expect(screen.getByText('原盘')).toBeInTheDocument() + expect(screen.getByText('FREE').closest('.v-chip')).toHaveClass('bg-lime-500') + expect(screen.getByText('50%').closest('.v-chip')).toHaveClass('bg-green-500') + expect(screen.getByText('2X').closest('.v-chip')).toHaveClass('bg-sky-500') + expect(screen.queryByText('1x')).not.toBeInTheDocument() + }) + + it('opens and closes the add-download boundary through all child outcomes', async () => { + server.use(siteCategoriesHandler(501, []), siteResourcesHandler(501, [createTorrentInfo({ title: '待下载资源' })])) + const user = userEvent.setup() + + await renderDialog() + const title = await screen.findByRole('button', { name: /待下载资源/ }) + + await user.click(title) + expect(screen.getByTestId('add-download-dialog')).toHaveTextContent('待下载资源') + await user.click(screen.getByRole('button', { name: 'done' })) + expect(screen.queryByTestId('add-download-dialog')).not.toBeInTheDocument() + + await user.click(title) + await user.click(screen.getByRole('button', { name: 'error' })) + expect(screen.queryByTestId('add-download-dialog')).not.toBeInTheDocument() + + await user.click(title) + await user.click(screen.getByRole('button', { name: 'close-download' })) + expect(screen.queryByTestId('add-download-dialog')).not.toBeInTheDocument() + }) + + it('corrects an out-of-range desktop page after the page size changes', async () => { + server.use( + siteCategoriesHandler(501, []), + siteResourcesHandler( + 501, + Array.from({ length: 30 }, (_, index) => createTorrentInfo({ title: `分页资源 ${index + 1}` })), + ), + ) + const user = userEvent.setup() + + await renderDialog(undefined, { VDataTable: DataTableStub }) + await screen.findByText('分页资源 1') + await user.click(screen.getByRole('button', { name: 'page-4' })) + expect(screen.getByTestId('resource-page')).toHaveTextContent('4') + await user.click(screen.getByRole('button', { name: 'per-page-100' })) + + await waitFor(() => expect(screen.getByTestId('resource-page')).toHaveTextContent('1')) + }) + + it('uses stable mobile keys and guards detail and torrent external links', async () => { + setViewport(390) + const open = vi.spyOn(window, 'open').mockImplementation(() => null) + server.use( + siteCategoriesHandler(501, []), + siteResourcesHandler(501, [ + createTorrentInfo({ + description: '移动端资源说明', + downloadvolumefactor: 0, + enclosure: 'https://tracker.example.com/download/one', + freedate_diff: '剩余 2 小时', + hit_and_run: true, + labels: ['移动标签'], + page_url: 'https://tracker.example.com/details/one', + title: '详情资源', + volume_factor: 'FREE', + }), + createTorrentInfo({ enclosure: 'magnet:?xt=urn:btih:test', page_url: '', title: '无外链资源' }), + createTorrentInfo({ enclosure: '', page_url: '', pubdate: '2026-07-19', title: '回退键资源' }), + ]), + ) + const user = userEvent.setup() + + await renderDialog() + expect(await screen.findByText('详情资源')).toBeInTheDocument() + expect(screen.getByText('移动端资源说明')).toBeInTheDocument() + expect(screen.getByText('移动标签')).toBeInTheDocument() + const cards = screen.getByTestId('progressive-grid').querySelectorAll('[data-resource-key]') + expect(Array.from(cards, card => card.getAttribute('data-resource-key'))).toEqual([ + 'https://tracker.example.com/details/one', + 'magnet:?xt=urn:btih:test', + '回退键资源-2026-07-19-2', + ]) + + await user.click(screen.getByRole('button', { name: /详情资源/ })) + await user.click(screen.getByRole('button', { name: 'close-download' })) + await user.click(screen.getAllByRole('button', { name: '添加下载' })[0]) + await user.click(screen.getByRole('button', { name: 'close-download' })) + + const detailButtons = screen.getAllByLabelText('查看详情') + await user.click(detailButtons[0]) + await user.click(detailButtons[1]) + await user.click(screen.getAllByLabelText('下载种子文件')[0]) + expect(open).toHaveBeenNthCalledWith(1, 'https://tracker.example.com/details/one', '_blank') + expect(open).toHaveBeenNthCalledWith(2, 'https://tracker.example.com/download/one', '_blank') + expect(open).toHaveBeenCalledTimes(2) + expect(screen.getAllByLabelText('下载种子文件')[1]).toBeDisabled() + }) + + it('expands and closes mobile search without retaining it after a desktop switch', async () => { + setViewport(390) + server.use(siteCategoriesHandler(501, []), siteResourcesHandler(501, [])) + const user = userEvent.setup() + + const { container } = await renderDialog() + await screen.findByText('没有数据') + const toggle = container.querySelector('.site-resource-mobile-search__toggle') + expect(toggle).not.toBeNull() + await user.click(toggle as HTMLElement) + await user.type(screen.getByLabelText('搜索关键字'), 'mobile') + await user.click(screen.getByRole('button', { name: '取消' })) + expect(screen.queryByLabelText('搜索关键字')).not.toBeInTheDocument() + + await user.click(toggle as HTMLElement) + setViewport(1280) + await waitFor(() => expect(container.querySelector('.site-resource-mobile-search')).toBeNull()) + setViewport(390) + await waitFor(() => expect(screen.queryByLabelText('搜索关键字')).not.toBeInTheDocument()) + }) + + it('emits close and formats the result summary in English', async () => { + server.use( + siteCategoriesHandler(501, []), + siteResourcesHandler(501, [createTorrentInfo({ title: 'Language resource' })]), + ) + const user = userEvent.setup() + + const { close, container } = await renderDialog() + await screen.findByText('Language resource') + i18n.global.locale.value = 'en-US' + expect(await screen.findByText('1 results')).toBeInTheDocument() + + const closeButton = container.querySelector('.v-toolbar-items .v-btn') + expect(closeButton).not.toBeNull() + await user.click(closeButton as HTMLElement) + expect(close).toHaveBeenCalledOnce() + }) +}) diff --git a/src/locales/en-US.ts b/src/locales/en-US.ts index d394ee41..e82fa7cb 100644 --- a/src/locales/en-US.ts +++ b/src/locales/en-US.ts @@ -3264,6 +3264,7 @@ export default { itemsPerPage: 'Items Per Page', noData: 'No Data', loading: 'Loading...', + loadFailed: 'Failed to load resources. Please retry.', titleColumn: 'Title', timeColumn: 'Time', sizeColumn: 'Size', diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index 9ae682e4..91d02024 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -3212,6 +3212,7 @@ export default { itemsPerPage: '每页条数', noData: '没有数据', loading: '加载中...', + loadFailed: '资源加载失败,请重试', titleColumn: '标题', timeColumn: '时间', sizeColumn: '大小', diff --git a/src/locales/zh-TW.ts b/src/locales/zh-TW.ts index 6855ba14..96b75b35 100644 --- a/src/locales/zh-TW.ts +++ b/src/locales/zh-TW.ts @@ -3212,6 +3212,7 @@ export default { pageText: '{0}-{1} 共 {2} 條', noData: '沒有數據', loading: '加載中...', + loadFailed: '資源加載失敗,請重試', titleColumn: '標題', timeColumn: '時間', sizeColumn: '大小', diff --git a/tests/support/factories/site.ts b/tests/support/factories/site.ts index 50e958ee..e5327740 100644 --- a/tests/support/factories/site.ts +++ b/tests/support/factories/site.ts @@ -1,6 +1,7 @@ -import type { DownloaderConf, Site, SiteStatistic, SiteUserData } from '@/api/types' +import type { DownloaderConf, Site, SiteCategory, SiteStatistic, SiteUserData, TorrentInfo } from '@/api/types' let siteSeed = 0 +let torrentSeed = 0 export function createSite(overrides: Partial = {}): Site { siteSeed += 1 @@ -49,3 +50,38 @@ export function createSiteDownloader(overrides: Partial = {}): D ...overrides, } } + +/** 构造站点资源分类测试记录。 */ +export function createSiteCategory(overrides: Partial = {}): SiteCategory { + return { + cat: 'movie', + desc: '电影', + id: 1, + ...overrides, + } +} + +/** 构造满足资源列表展示与下载边界的种子记录。 */ +export function createTorrentInfo(overrides: Partial = {}): TorrentInfo { + torrentSeed += 1 + return { + category: '电影', + downloadvolumefactor: 1, + freedate: '', + freedate_diff: '', + grabs: 10, + hit_and_run: false, + imdbid: '', + labels: [], + peers: 3, + pri_order: 0, + seeders: 12, + site_order: 0, + site_proxy: false, + size: 1_073_741_824, + title: `测试资源 ${torrentSeed}`, + uploadvolumefactor: 1, + volume_factor: '1x', + ...overrides, + } +} diff --git a/tests/support/msw/handlers/site.ts b/tests/support/msw/handlers/site.ts index ecc856c2..ae4e72ba 100644 --- a/tests/support/msw/handlers/site.ts +++ b/tests/support/msw/handlers/site.ts @@ -1,4 +1,12 @@ -import type { ApiResponse, DownloaderConf, Site, SiteStatistic, SiteUserData } from '@/api/types' +import type { + ApiResponse, + DownloaderConf, + Site, + SiteCategory, + SiteStatistic, + SiteUserData, + TorrentInfo, +} from '@/api/types' import { HttpResponse, http, type JsonBodyType } from 'msw' const API_BASE_URL = 'http://localhost/api/v1/' @@ -10,6 +18,7 @@ interface SiteMutationResponse { } export const siteApiUrls = { + categories: (siteId: number) => new URL(`site/category/${siteId}`, API_BASE_URL).href, cookie: (id: number) => new URL(`site/cookie/${id}`, API_BASE_URL).href, delete: (id: number) => new URL(`site/${id}`, API_BASE_URL).href, details: (id: number) => new URL(`site/${id}`, API_BASE_URL).href, @@ -17,6 +26,7 @@ export const siteApiUrls = { icon: (id: number) => new URL(`site/icon/${id}`, API_BASE_URL).href, list: new URL('site/', API_BASE_URL).href, priorities: new URL('site/priorities', API_BASE_URL).href, + resources: (siteId: number) => new URL(`site/resource/${siteId}`, API_BASE_URL).href, statistic: (domain: string) => new URL(`site/statistic/${domain}`, API_BASE_URL).href, statistics: new URL('site/statistic', API_BASE_URL).href, test: (id: number) => new URL(`site/test/${id}`, API_BASE_URL).href, @@ -180,3 +190,27 @@ export function updateSiteCookieHandler( return HttpResponse.json(response, { status }) }) } + +export function siteCategoriesHandler( + siteId: number, + response: SiteCategory[], + status = 200, + onRequest: (url: URL) => void = () => {}, +) { + return http.get(siteApiUrls.categories(siteId), ({ request }) => { + onRequest(new URL(request.url)) + return HttpResponse.json(response, { status }) + }) +} + +export function siteResourcesHandler( + siteId: number, + response: TorrentInfo[], + status = 200, + onRequest: (url: URL) => void = () => {}, +) { + return http.get(siteApiUrls.resources(siteId), ({ request }) => { + onRequest(new URL(request.url)) + return HttpResponse.json(response, { status }) + }) +} diff --git a/vite.config.ts b/vite.config.ts index 4b680117..e6fc2abe 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -301,6 +301,7 @@ export default defineConfig(({ mode }) => ({ 'src/components/dialog/SubscribeShareDialog.vue', 'src/components/dialog/SubscribeShareStatisticsDialog.vue', 'src/components/dialog/DiscoverTabOrderDialog.vue', + 'src/components/dialog/SiteResourceDialog.vue', 'src/views/discover/TheMovieDbView.vue', 'src/views/discover/DoubanView.vue', 'src/views/discover/BangumiView.vue', @@ -485,6 +486,12 @@ export default defineConfig(({ mode }) => ({ lines: 80, statements: 80, }, + 'src/components/dialog/SiteResourceDialog.vue': { + branches: 85, + functions: 90, + lines: 90, + statements: 90, + }, 'src/views/discover/TheMovieDbView.vue': { branches: 75, functions: 80,