使用chart.js时创建react jest测试用例时出现问题

mgdq6dx1  于 11个月前  发布在  Jest
关注(0)|答案(1)|浏览(132)

bounty明天到期。回答此问题有资格获得+200声望奖励。Shruti sharma正在寻找规范答案

我有下面的测试用例.请不要阅读整个代码.(它没有必要).我想说的是我写了至少100倍,检查与chatgpt,谷歌巴德仍然无法使这个测试用例成功.对于所有其他组件所有的测试用例都成为成功.下面是我的代码.(仅供参考).

import React, { useEffect, useRef, useState } from 'react';
import { Chart, ChartConfiguration, registerables } from 'chart.js';
import './EmailLineChart.styles.css';
import { useUser } from '../../common/context/context';

const DataLineChart: React.FC = () => {
    const chartRef = useRef<HTMLCanvasElement>(null);
    const chartInstanceRef = useRef<Chart | null>(null);
    const [data, setData] = useState<{ month: string; success: number; failed: number; processing?: number }[]>([]);
    const [downloadFormat, setDownloadFormat] = useState<string>('chart');
    const [filterMonth, setFilterMonth] = useState<string>('');
    const [chartType, setChartType] = useState<'line'|'bar'>('line');

   
    const baseUrl = process.env.REACT_APP_BASE_URL;

    let url = `${baseUrl}/email/reports/count?type=year&tag=${tag}&service_name=${servicename}`;
    const tenantData = useUser();
  

    useEffect(() => {
        const fetchData = async () => {
            try {
                const response = await fetch(url);
                const apiData = await response.json();
                const monthlyReports = apiData.monthlyReports;
            

                if (!monthlyReports) {
                    console.error('No monthlyReports data in API response');
                    return;  // Early return if no monthlyReports data
                }

                const chartData = Object.keys(monthlyReports).map((month) => ({
                    month,
                    success: monthlyReports[month].SUCCESS,
                    failed: monthlyReports[month].FAILED,
                    processing: monthlyReports[month].PROCESSING || 0,
                }));
                // Sort data by month
                chartData.sort((a, b) => new Date(a.month).getTime() - new Date(b.month).getTime());
                setData(chartData);
            } catch (error) {
                console.error('Error fetching data:', error);
            }
        };
        fetchData();
    }, []);
    useEffect(() => {
        if (chartInstanceRef.current) {
            chartInstanceRef.current.destroy();
        }
        if (chartRef.current && downloadFormat === 'chart') {
            Chart.register(...registerables);
            const ctx = chartRef.current.getContext('2d');
            const filteredData = filterMonth ? data.filter((item) => item.month === filterMonth) : data;
            if (ctx) {
                const gradient1 = ctx.createLinearGradient(0, 0, 0, 400);
                gradient1.addColorStop(0, 'rgba(75, 192, 192, 0.6)');
                gradient1.addColorStop(1, 'rgba(75, 192, 192, 0)');
              
                const gradient2 = ctx.createLinearGradient(0, 0, 0, 400);
                gradient2.addColorStop(0, 'rgba(255, 99, 132, 0.6)');
                gradient2.addColorStop(1, 'rgba(255, 99, 132, 0)');
                
                const config: ChartConfiguration<'line'|'bar'> = {
                    type: chartType,
                    data: {
                        labels: filteredData.map((item) => item.month),
                        datasets: [
                            {
                                label: 'Success',
                                data:  filteredData.map((item) => item.success),
                                borderColor:  'rgba(75, 192,198, 0.9)',
                                fill: true,
                                backgroundColor:'rgba(75, 192, 192, 0.3)',
                                pointBackgroundColor: 'rgba(75, 192, 192, 0.9)',
                                pointBorderColor:'rgba(75, 250, 192, 0.9)',
                                pointHoverBackgroundColor: 'rgba(75, 350, 192, 0.9)',
                                pointHoverBorderColor: 'rgba(75, 350, 192, 0.9)',
                                pointHoverRadius: 8,
                                pointHoverBorderWidth: 5,
                                tension: 0.1,
                            },
                            {
                                label: 'Failed',
                                data:  filteredData.map((item) => item.failed),
                                borderColor: 'rgba(255, 99, 132, 0.4)',
                                fill: true,
                                backgroundColor: 'rgba(255, 99, 132, 0.2)',
                                pointBackgroundColor: 'rgba(255, 99, 132, 0.3)',
                                pointBorderColor: 'rgba(255, 99, 132, 0.9)',
                                pointHoverBackgroundColor: 'rgba(255, 99, 132, 0.3)',
                                pointHoverBorderColor: 'rgba(255, 99, 132, 0.3)',
                                pointHoverRadius: 8,
                                pointHoverBorderWidth: 5,
                                tension: 0.1,
                            },
                        ],
                    },
                    options: {
                        responsive: true,
                        animation: {
                            duration: 2000,
                            easing: 'easeInOutBounce',
                        },
                        scales: {
                            x: {
                                title: {
                                    display: true,
                                    text: 'Month',
                                },
                                grid: {
                                    color: 'gray', // change this as needed
                                    display: false,
                                },
                                ticks: {
                                    color: 'black', // change this as needed
                                    font: {
                                        size: 10,
                                    }
                                },
                                stacked:true
                            },
                            y: {
                                title: {
                                    display: true,
                                    text: 'Number of Emails',
                                },
                                ticks: {
                                    color: 'black', // change this as needed
                                    font: {
                                        size: 10,
                                    }
                                },
                                grid: {
                                    color: 'gray', // change this as needed
                                    display: false,
                                },
                                stacked:true,
                            },
                        }
                    }
                    ,                      
                };
                chartInstanceRef.current = new Chart(ctx, config);
            }
        }
          
          
    }, [downloadFormat, data, filterMonth]); 
  
    useEffect(() => {
        if (chartInstanceRef.current) {
            const chart = chartInstanceRef.current;
            chart.data.labels = data.map((item) => item.month);
            chart.data.datasets[0].data = data.map((item) => item.success||0);
            chart.data.datasets[1].data = data.map((item) => item.failed||0);
            chart.update();
        }
    }, [data]);

    
    const filteredData = filterMonth ? data.filter((item) => item.month === filterMonth) : data;
    const isChartSelected = downloadFormat === 'chart';

    return (
        <div className='chart'>
                <canvas ref={chartRef} className='chart-wrapper'></canvas>           
        </div>
    );
};
export default DataLineChart;

字符串
由于我的代码使用自定义钩子和chart.js,所以很难写案例,但它只在渲染时出错。我根本无法前进。
我写了下面的测试用例。

import React from 'react';
import { render } from '@testing-library/react';
import { Chart, registerables } from 'chart.js'; // Import Chart.js as usual
import DataLineChart from './DataLineChart';

jest.mock('../../common/context/context', () => ({
  useUser: jest.fn(() => ({ tenantData: { tenantId: 'mockedTenantId' } })),
}));

jest.mock('chart.js')

describe('DataLineChart', () => {
  it('renders without errors', () => {
    render(<DataLineChart />);
  });
});


但错误即将来临

"TypeError: undefined is not iterable (cannot read property Symbol(symbol.iterator)"


基本上错误来自这一行。Chart.register(...registerables);。你们中的任何人都可以指导如何模拟chart.js。如何测试这些类型的组件?我有95%代码覆盖率和挣扎严重的最后10天.我用了很多方法来模拟chart.js,但没有任何工作. chart.js我使用3.9.1版本.如果任何建议修改代码或测试用例,将真的很有帮助。我使用jest。我也可以提供完整版本的代码,如果它是有帮助的,无论如何。

wgeznvg7

wgeznvg71#

我认为这里的问题是你试图在一个超级大的函数中做太多的事情。理想情况下,你需要将useEffects()从React Functional Component中取出,然后将它们分解为更小的可测试函数。
如果我在写这个,我会把每个效果放在它们自己的文件中,然后把每个效果分解成更小的函数,然后通过一个非常小的useEffect()调用来调用。
这样,您就可以为每个功能编写单独的测试。
我个人的经验法则是,如果一个函数做多个离散的事情,它需要拆分成更小的函数。一旦你开始用清晰的函数名来做这件事,你的代码库立即变得自我文档化,如果你在一年后不得不回到这段代码,你会感谢你的。
这很可能不是你想要的答案,但很久以前,它是我收到的最好的编码建议之一。

相关问题