import { ComponentFixture, TestBed } from '@angular/core/testing'; import { provideMarkdown } from 'ngx-markdown'; import { Message } from '../../../core/api/models'; import { MessageBubbleComponent } from './message-bubble'; /** * 文件 / 图片卡片(2026-10-30 重做) * * 锁住三件事:主区可点开、下载是独立按钮、两者互不触发。 */ describe('MessageBubble 文件卡片', () => { let fixture: ComponentFixture; function render(m: Message): void { fixture = TestBed.createComponent(MessageBubbleComponent); fixture.componentRef.setInput('message', m); fixture.componentRef.setInput('own', false); fixture.detectChanges(); } beforeEach(async () => { await TestBed.configureTestingModule({ imports: [MessageBubbleComponent], providers: [provideMarkdown()], }).compileComponents(); }); it('非图片文件渲染为卡片,含主区与下载按钮', () => { render({ id: 'm1', conversationId: 'c', sender: 'agent', kind: 'text', ts: new Date().toISOString(), state: 'sent', file: { kind: 'file', name: '报告.html', size: 1024, mimeType: 'text/html', url: 'https://x/a.html', }, }); expect(fixture.nativeElement.querySelector('.file-card')).not.toBeNull(); expect(fixture.nativeElement.querySelector('.file-main')).not.toBeNull(); expect(fixture.nativeElement.querySelectorAll('.file-act').length).toBe(2); }); it('点下载按钮只下载,不触发预览', () => { render({ id: 'm1', conversationId: 'c', sender: 'agent', kind: 'text', ts: new Date().toISOString(), state: 'sent', file: { kind: 'file', name: 'a.html', size: 1, mimeType: 'text/html', url: 'https://x/a.html' }, }); const previews: unknown[] = []; fixture.componentInstance.preview.subscribe((f) => previews.push(f)); const link: HTMLAnchorElement = fixture.nativeElement.querySelectorAll('.file-act')[1]; /* * 🔴 必须先拦掉默认行为: 在 Karma 里会真的发起导航, * 表现为 "Some of your tests did a full page reload!" 然后整个 runner 断连。 */ const stop = (e: Event) => e.preventDefault(); link.addEventListener('click', stop); link.click(); link.removeEventListener('click', stop); // 下载是 ,不经过 preview 输出 expect(previews.length).toBe(0); expect(link.getAttribute('download')).toBe('a.html'); }); it('点主区触发预览', () => { render({ id: 'm1', conversationId: 'c', sender: 'agent', kind: 'text', ts: new Date().toISOString(), state: 'sent', file: { kind: 'file', name: 'a.png', size: 1, mimeType: 'image/png', url: 'https://x/a.png' }, }); let got = 0; fixture.componentInstance.preview.subscribe(() => got++); (fixture.nativeElement.querySelector('button[aria-label="预览图片 a.png"]') as HTMLElement).click(); expect(got).toBe(1); }); });