frontend/test/feedback.test.ts
Rama master · réplica de lectura del repositorio original.
import {describe,expect,it} from 'vitest';
import {requestErrorMessage} from '../src/core';
import {noteHtml,projectBannerHtml,gaugeHtml,progressHtml,configurationSkeletonHtml} from '../src/ui-kit';
describe('中文错误反馈',()=>{
it.each(['Failed to fetch','NetworkError when attempting to fetch resource.','Load failed'])('网络异常 %s 给出连接检查方法',message=>{
expect(requestErrorMessage(new TypeError(message))).toBe('无法连接到 Peach 服务,请确认网络连接和托盘服务已启动。');
});
it.each([[401,'登录已失效'],[403,'没有执行此操作的权限'],[404,'已不存在'],[429,'过于频繁'],[503,'暂时不可用'],[504,'超时']])('HTTP %s 使用明确原因', (code,reason)=>{
expect(requestErrorMessage('request failed',code)).toContain(reason);
});
it('正文里的 timeout 字样不把 500 读成超时',()=>{
expect(requestErrorMessage('Traceback: httpx.ReadTimeout raised in handler (timeout=30)',500))
.toBe('Peach 服务处理失败,请重试;持续失败时查看托盘日志。');
expect(requestErrorMessage('read timed out')).toContain('超时');
});
it('本机接口的 502 说的是 Peach 服务,不提代理',()=>{
const text=requestErrorMessage('Bad Gateway',502);
expect(text).toContain('Peach 服务');
expect(text).not.toContain('代理');
});
it('保留服务端明确的中文原因',()=>{
expect(requestErrorMessage('媒体盘没有挂载,请先连接媒体盘。',409)).toBe('媒体盘没有挂载,请先连接媒体盘。');
});
});
describe('持久提示控件',()=>{
it('配置骨架标题和卡片共用真实页面网格与正文底栏',()=>{
const host=document.createElement('div');host.innerHTML=configurationSkeletonHtml();
const page=host.querySelector('.ui-configpage')!;
expect(page.querySelectorAll(':scope > .ui-configgroup')).toHaveLength(5);
expect(page.querySelectorAll(':scope > .configfieldset')).toHaveLength(12);
for(const card of page.querySelectorAll('.configfieldset')){
expect(card.querySelector(':scope > .geist-fieldset-content')).not.toBeNull();
expect(card.querySelector(':scope > .geist-fieldset-footer')).not.toBeNull();
}
expect(host.children).toHaveLength(1);
});
it.each([[79,'normal'],[80,'warning'],[94,'warning'],[95,'error']])('容量 %s 使用一致阈值', (value,level)=>{
const host=document.createElement('div');host.innerHTML=gaugeHtml('空间使用率',value,100,{usage:true});
expect(host.querySelector('.ui-geist-gauge')?.getAttribute('data-level')).toBe(level);
expect(gaugeHtml('完成率',value,100)).toContain('data-level="normal"');
});
it('失败提示包含一个次要样式的内部操作按钮',()=>{
const host=document.createElement('div');host.innerHTML=noteHtml('来源离线',{variant:'error',filled:true,actionLabel:'立即重试'});
const buttons=host.querySelectorAll('[role=alert] button');
expect(buttons).toHaveLength(1);
expect(buttons[0]!.classList.contains('primary')).toBe(false);
});
it('容量比例和任务计数使用真实上限,未知容量不显示零',()=>{
const host=document.createElement('div');host.innerHTML=gaugeHtml('使用率',25,50);
expect(host.querySelector('[role=progressbar]')?.getAttribute('aria-valuenow')).toBe('50');
expect(gaugeHtml('使用率',0,0)).toContain('未取得');
host.innerHTML=progressHtml('分析记录',3,10,{stops:[{value:5,label:'分析结束'}],variant:'warning'});
expect(host.querySelector('[role=progressbar]')?.getAttribute('aria-valuemax')).toBe('10');
expect(host.querySelector('[aria-label="分析结束"]')).not.toBeNull();
});
it('Note 错误不会直接输出英文网络异常',()=>{
const host=document.createElement('div');host.innerHTML=noteHtml('Failed to fetch',{variant:'error',size:'small',filled:true});
expect(host.querySelector('[role=alert]')?.textContent).toContain('无法连接到 Peach');
expect(host.querySelector('.geist-note-small.geist-note-filled')).not.toBeNull();
expect(host.querySelector('button')).toBeNull();
});
it('Project Banner 包含处理入口且没有关闭键',()=>{
const host=document.createElement('div');host.innerHTML=projectBannerHtml('扫描未完成',{variant:'warning',href:'/data-cleanup',label:'查看并处理'});
expect(host.querySelector('.ui-project-banner-warning')).not.toBeNull();
expect(host.querySelector('a')?.getAttribute('href')).toBe('/data-cleanup');
expect(host.querySelector('button')).toBeNull();
});
});