import React from 'react'; import { render } from '@testing-library/react'; import PluginIcon from '../../src/components/Designer/PluginIcon'; import { Plugin, Schema } from '@pdfme/common'; import { OptionsContext } from '../../src/contexts'; // Mock Ant Design theme vi.mock('antd', () => ({ theme: { useToken: () => ({ token: { colorText: '#000' } }), }, })); const mockPlugin: Plugin = { propPanel: { schema: {}, defaultSchema: { type: 'text', name: 'test', width: 50, height: 20, position: { x: 0, y: 0 }, }, }, icon: '', ui: () => {}, pdf: () => Promise.resolve(), }; const renderPluginIcon = ( plugin: Plugin = mockPlugin, options = {}, props = {} ) => { return render( ); }; describe('PluginIcon Security Tests', () => { beforeEach(() => { // Clear any previous DOM purify configurations vi.clearAllMocks(); }); test('renders safe SVG icon correctly', () => { const safeSVG = ''; const plugin = { ...mockPlugin, icon: safeSVG }; const { container } = renderPluginIcon(plugin); const svgDiv = container.querySelector('div[title="Test Plugin"]'); expect(svgDiv).toBeInTheDocument(); expect(svgDiv?.innerHTML).toContain(' { const maliciousSVG = ''; const plugin = { ...mockPlugin, icon: maliciousSVG }; const { container } = renderPluginIcon(plugin); const svgDiv = container.querySelector('div[title="Test Plugin"]'); expect(svgDiv).toBeInTheDocument(); expect(svgDiv?.innerHTML).not.toContain(' { const maliciousSVG = ''; const plugin = { ...mockPlugin, icon: maliciousSVG }; const { container } = renderPluginIcon(plugin); const svgDiv = container.querySelector('div[title="Test Plugin"]'); expect(svgDiv).toBeInTheDocument(); expect(svgDiv?.innerHTML).not.toContain(' { const maliciousSVG = ''; const plugin = { ...mockPlugin, icon: maliciousSVG }; const { container } = renderPluginIcon(plugin); const svgDiv = container.querySelector('div[title="Test Plugin"]'); expect(svgDiv).toBeInTheDocument(); expect(svgDiv?.innerHTML).not.toContain(' { const maliciousSVG = ''; const plugin = { ...mockPlugin, icon: maliciousSVG }; const { container } = renderPluginIcon(plugin); const svgDiv = container.querySelector('div[title="Test Plugin"]'); expect(svgDiv).toBeInTheDocument(); expect(svgDiv?.innerHTML).not.toContain('onclick'); expect(svgDiv?.innerHTML).not.toContain('onload'); }); test('removes namespaced event handlers', () => { const maliciousSVG = ''; const plugin = { ...mockPlugin, icon: maliciousSVG }; const { container } = renderPluginIcon(plugin); const svgDiv = container.querySelector('div[title="Test Plugin"]'); expect(svgDiv).toBeInTheDocument(); expect(svgDiv?.innerHTML).not.toContain('ev:onclick'); }); test('preserves safe SVG attributes', () => { const safeSVG = ''; const plugin = { ...mockPlugin, icon: safeSVG }; const { container } = renderPluginIcon(plugin); const svgDiv = container.querySelector('div[title="Test Plugin"]'); expect(svgDiv).toBeInTheDocument(); expect(svgDiv?.innerHTML).toContain('viewBox'); expect(svgDiv?.innerHTML).toContain('fill="blue"'); expect(svgDiv?.innerHTML).toContain('stroke="red"'); }); test('applies size attributes correctly', () => { const safeSVG = ''; const plugin = { ...mockPlugin, icon: safeSVG }; const { container } = renderPluginIcon(plugin, {}, { size: 48 }); const svgDiv = container.querySelector('div[title="Test Plugin"]'); expect(svgDiv).toBeInTheDocument(); expect(svgDiv?.innerHTML).toContain('width="48"'); expect(svgDiv?.innerHTML).toContain('height="48"'); }); test('handles invalid SVG gracefully', () => { const invalidSVG = 'not an svg'; const plugin = { ...mockPlugin, icon: invalidSVG }; const { container } = renderPluginIcon(plugin); // When SVG is invalid and sanitization results in empty, should render empty div or nothing expect(container).toBeInTheDocument(); }); test('uses custom icon from options.icons', () => { const customSVG = ''; const options = { icons: { text: customSVG } }; const { container } = renderPluginIcon(mockPlugin, options); const svgDiv = container.querySelector('div[title="Test Plugin"]'); expect(svgDiv).toBeInTheDocument(); expect(svgDiv?.innerHTML).toContain(' { const pluginWithoutIcon = { ...mockPlugin, icon: undefined, }; const { container } = renderPluginIcon(pluginWithoutIcon); const textDiv = container.querySelector('div[title="Test Plugin"]'); expect(textDiv).toBeInTheDocument(); expect(textDiv?.textContent).toBe('Test Plugin'); }); test('prevents multiple XSS attack vectors simultaneously', () => { const complexMaliciousSVG = ` `; const plugin = { ...mockPlugin, icon: complexMaliciousSVG }; const { container } = renderPluginIcon(plugin); const svgDiv = container.querySelector('div[title="Test Plugin"]'); expect(svgDiv).toBeInTheDocument(); // Verify all malicious elements are removed expect(svgDiv?.innerHTML).not.toContain('