fix(learning): load readme images over https

This commit is contained in:
2026-08-20 13:51:48 +08:00
parent 28bfd8bc3e
commit 9956739693
6 changed files with 103 additions and 7 deletions

View File

@@ -17,7 +17,9 @@ vi.mock('@/lib/learning', () => ({
}));
vi.mock('@/pages/Learning/ProjectImage', () => ({
ProjectImage: ({ src, alt }: { src: string; alt: string }) => <img src={src} alt={alt} />,
ProjectImage: ({ src, alt, allowHttps }: { src: string; alt: string; allowHttps?: boolean }) => (
<img src={src} alt={alt} data-allow-https={allowHttps ? 'true' : 'false'} />
),
}));
const project = {
@@ -74,12 +76,12 @@ describe('Learning project pages', () => {
expect(fetchLearningProjectsMock).toHaveBeenNthCalledWith(2, { cursor: 'cursor-2', limit: 24 });
});
it('renders Markdown without raw HTML and keeps remote README media on the controlled path', async () => {
it('renders Markdown without raw HTML and allows direct HTTPS README images', async () => {
fetchLearningProjectMock.mockResolvedValue({
...project,
archiveFileName: 'robot-arm.zip',
archiveSha256: 'a'.repeat(64),
readmeMarkdown: '# 开始搭建\n\n![接线图](/api/learning/projects/robot-arm/media/wiring)\n\n<script>bad()</script>\n\n[参考资料](https://example.com/guide)',
readmeMarkdown: '# 开始搭建\n\n![接线图](https://images.example.com/wiring.svg)\n\n<script>bad()</script>\n\n[参考资料](https://example.com/guide)',
});
render(
<MemoryRouter initialEntries={['/learning/project/robot-arm']}>
@@ -90,8 +92,9 @@ describe('Learning project pages', () => {
expect(await screen.findByRole('heading', { name: '开始搭建' })).toBeInTheDocument();
expect(screen.getByAltText('接线图')).toHaveAttribute(
'src',
'/api/learning/projects/robot-arm/media/wiring',
'https://images.example.com/wiring.svg',
);
expect(screen.getByAltText('接线图')).toHaveAttribute('data-allow-https', 'true');
expect(document.querySelector('script')).toBeNull();
fireEvent.click(screen.getByRole('link', { name: '参考资料' }));
expect(openLearningExternalLinkMock).toHaveBeenCalledWith('https://example.com/guide');

View File

@@ -0,0 +1,30 @@
import { render, screen } from '@testing-library/react';
import { describe, expect, it } from 'vitest';
import { ProjectImage } from '@/pages/Learning/ProjectImage';
describe('Learning ProjectImage', () => {
it('renders a credential-free HTTPS image only when direct loading is allowed', () => {
const { rerender } = render(
<ProjectImage
src="https://images.example.com/diagram.svg"
alt="项目结构图"
allowHttps
/>,
);
expect(screen.getByAltText('项目结构图')).toHaveAttribute(
'src',
'https://images.example.com/diagram.svg',
);
rerender(
<ProjectImage
src="https://images.example.com/diagram.svg"
alt="项目结构图"
/>,
);
expect(screen.queryByAltText('项目结构图')).not.toBeInTheDocument();
expect(screen.getByRole('img', { name: '项目结构图加载失败' })).toBeInTheDocument();
});
});