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:
LingandRX
2026-06-05 12:53:19 +08:00
committed by GitHub
parent 0624b609be
commit 359326c6da
4 changed files with 57 additions and 32 deletions
+29 -13
View File
@@ -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('编辑'));
+18 -14
View File
@@ -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]);
/** 返回编辑态,保留上次输入内容 */
+2 -2
View File
@@ -103,8 +103,8 @@ export function parseContextMenuClick(
): ParseResult {
const featureKey = getMenuPageType(menuItemId);
// 处理图片 URL(右键点击图片时)
if (info.srcUrl) {
// 处理图片 URL仅 qrCode-image 菜单项,右键点击图片时)
if (menuItemId === 'qrCode-image' && info.srcUrl) {
return {
success: true,
data: { featureKey, payload: info.srcUrl },