Hotfix/contextmenu srcurl generating fix (#63)
* fix: 修复右键菜单 srcUrl 误判、pre-push 全量扫描、generating 状态不可见问题 - contextMenu: srcUrl 检查限定为 qrCode-image 菜单项,避免其他菜单误返回图片 URL - pre-push: eslint 改为只检查变更文件(git diff 过滤),tsc 保留全项目检查 - useQrCode: confirmGenerate 用 setTimeout 延迟生成,让 loading 状态先被 React 渲染 - tests: 生成相关测试改为 async + waitFor 适配异步 confirmGenerate * fix(hooks): pre-push 无 upstream 时回退到 origin/main 对比
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import QrCodePage from '../index';
|
||||
|
||||
vi.mock('lucide-react', async (importOriginal) => {
|
||||
@@ -102,7 +102,7 @@ describe('QrCodePage', () => {
|
||||
expect(generateButton).not.toBeDisabled();
|
||||
});
|
||||
|
||||
it('点击生成按钮应该切换到预览态', () => {
|
||||
it('点击生成按钮应该切换到预览态', async () => {
|
||||
render(<QrCodePage />);
|
||||
|
||||
// 输入文本
|
||||
@@ -114,14 +114,16 @@ describe('QrCodePage', () => {
|
||||
fireEvent.click(generateButton);
|
||||
|
||||
// 验证切换到预览态
|
||||
expect(screen.getByText('原始文本')).toBeInTheDocument();
|
||||
expect(screen.getByText('编辑')).toBeInTheDocument();
|
||||
expect(screen.queryByText('生成二维码')).not.toBeInTheDocument();
|
||||
// 预览态应该显示二维码
|
||||
expect(screen.getByTestId('qr-code-preview')).toBeInTheDocument();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('原始文本')).toBeInTheDocument();
|
||||
expect(screen.getByText('编辑')).toBeInTheDocument();
|
||||
expect(screen.queryByText('生成二维码')).not.toBeInTheDocument();
|
||||
// 预览态应该显示二维码
|
||||
expect(screen.getByTestId('qr-code-preview')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('预览态应该显示截断的文本', () => {
|
||||
it('预览态应该显示截断的文本', async () => {
|
||||
render(<QrCodePage />);
|
||||
|
||||
// 输入长文本
|
||||
@@ -135,10 +137,12 @@ describe('QrCodePage', () => {
|
||||
|
||||
// 验证显示截断的文本(80字符 + "...")
|
||||
const truncatedText = longText.slice(0, 80) + '...';
|
||||
expect(screen.getByText(truncatedText)).toBeInTheDocument();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(truncatedText)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('预览态应该显示完整的短文本', () => {
|
||||
it('预览态应该显示完整的短文本', async () => {
|
||||
render(<QrCodePage />);
|
||||
|
||||
// 输入短文本
|
||||
@@ -150,10 +154,12 @@ describe('QrCodePage', () => {
|
||||
fireEvent.click(screen.getByText('生成二维码'));
|
||||
|
||||
// 验证显示完整文本
|
||||
expect(screen.getByText(shortText)).toBeInTheDocument();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(shortText)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('点击编辑按钮应该返回输入态', () => {
|
||||
it('点击编辑按钮应该返回输入态', async () => {
|
||||
render(<QrCodePage />);
|
||||
|
||||
// 输入文本并生成
|
||||
@@ -161,6 +167,11 @@ describe('QrCodePage', () => {
|
||||
fireEvent.change(textarea, { target: { value: 'https://example.com' } });
|
||||
fireEvent.click(screen.getByText('生成二维码'));
|
||||
|
||||
// 等待生成完成
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('编辑')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
// 点击编辑按钮
|
||||
fireEvent.click(screen.getByText('编辑'));
|
||||
|
||||
@@ -172,7 +183,7 @@ describe('QrCodePage', () => {
|
||||
expect(screen.queryByTestId('qr-code-preview')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('返回编辑态应该保留上次输入的内容', () => {
|
||||
it('返回编辑态应该保留上次输入的内容', async () => {
|
||||
render(<QrCodePage />);
|
||||
|
||||
// 输入文本并生成
|
||||
@@ -180,6 +191,11 @@ describe('QrCodePage', () => {
|
||||
fireEvent.change(textarea, { target: { value: 'https://example.com' } });
|
||||
fireEvent.click(screen.getByText('生成二维码'));
|
||||
|
||||
// 等待生成完成
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('编辑')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
// 点击编辑按钮
|
||||
fireEvent.click(screen.getByText('编辑'));
|
||||
|
||||
|
||||
@@ -165,27 +165,31 @@ export function useQrCode(): QrCodeContextValue {
|
||||
return;
|
||||
}
|
||||
|
||||
// 先设置 loading 状态,让 React 渲染加载动画
|
||||
setGeneratorState((prev) => ({ ...prev, generating: true, inputError: '' }));
|
||||
|
||||
const qrCodeDataUrl = generateQrCodeDataUrl(text);
|
||||
// 延迟到下一帧生成,确保 loading 状态先被渲染显示
|
||||
setTimeout(() => {
|
||||
const qrCodeDataUrl = generateQrCodeDataUrl(text);
|
||||
|
||||
if (!qrCodeDataUrl) {
|
||||
setGeneratorState((prev) => ({
|
||||
...prev,
|
||||
generating: false,
|
||||
inputError: t('qrCode:generateError'),
|
||||
}));
|
||||
toast.error(t('qrCode:generateError'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!qrCodeDataUrl) {
|
||||
setGeneratorState((prev) => ({
|
||||
...prev,
|
||||
step: 'preview',
|
||||
savedText: text,
|
||||
qrCodeDataUrl,
|
||||
generating: false,
|
||||
inputError: t('qrCode:generateError'),
|
||||
}));
|
||||
toast.error(t('qrCode:generateError'));
|
||||
return;
|
||||
}
|
||||
|
||||
setGeneratorState((prev) => ({
|
||||
...prev,
|
||||
step: 'preview',
|
||||
savedText: text,
|
||||
qrCodeDataUrl,
|
||||
generating: false,
|
||||
}));
|
||||
}, 0);
|
||||
}, [generatorState.textToEncode, t]);
|
||||
|
||||
/** 返回编辑态,保留上次输入内容 */
|
||||
|
||||
Reference in New Issue
Block a user