Compare commits

..

5 Commits

Author SHA1 Message Date
雨霖铃 10644fae95 fix(hooks): pre-push 无 upstream 时回退到 origin/main 对比 2026-06-05 12:50:55 +08:00
雨霖铃 77f722b575 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
2026-06-05 12:49:43 +08:00
LingandRX 0624b609be Merge pull request #62 from LingandRX/hotfix/remove-unused-alarms
hotfix: remove unused alarms permission
2026-06-02 19:10:26 +08:00
Ubuntu f551428142 hotfix: remove unused alarms permission 2026-06-02 19:09:39 +08:00
LingandRX 1ae057ccfa Merge pull request #61 from LingandRX/hotfix/revert-version
hotfix: revert package.json version to 1.0.0
2026-06-02 14:59:34 +08:00
6 changed files with 57 additions and 40 deletions
+8 -3
View File
@@ -1,6 +1,11 @@
# pre-push: 严格检查,阻塞有问题的代码推送到远程
# 类型检查
# 类型检查(全项目,因为类型错误可能跨文件传播)
npx tsc --noEmit
# ESLint 严格检查(不允许 warning
npx eslint . --max-warnings=0
# ESLint 严格检查(仅检查本次推送的变更文件,不阻塞不相关的旧代码
# 新分支无 upstream 时,回退到与 origin/main 对比
BASE=$(git rev-parse --verify @{upstream} 2>/dev/null && echo "@{upstream}" || echo "origin/main")
CHANGED_FILES=$(git diff --name-only --diff-filter=d "$BASE"...HEAD -- '*.ts' '*.tsx' '*.js' '*.jsx' '*.mjs')
if [ -n "$CHANGED_FILES" ]; then
echo "$CHANGED_FILES" | xargs npx eslint --max-warnings=0
fi
+22 -6
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);
// 验证切换到预览态
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) + '...';
await waitFor(() => {
expect(screen.getByText(truncatedText)).toBeInTheDocument();
});
});
it('预览态应该显示完整的短文本', () => {
it('预览态应该显示完整的短文本', async () => {
render(<QrCodePage />);
// 输入短文本
@@ -150,10 +154,12 @@ describe('QrCodePage', () => {
fireEvent.click(screen.getByText('生成二维码'));
// 验证显示完整文本
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('编辑'));
+4
View File
@@ -165,8 +165,11 @@ export function useQrCode(): QrCodeContextValue {
return;
}
// 先设置 loading 状态,让 React 渲染加载动画
setGeneratorState((prev) => ({ ...prev, generating: true, inputError: '' }));
// 延迟到下一帧生成,确保 loading 状态先被渲染显示
setTimeout(() => {
const qrCodeDataUrl = generateQrCodeDataUrl(text);
if (!qrCodeDataUrl) {
@@ -186,6 +189,7 @@ export function useQrCode(): QrCodeContextValue {
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 },
-7
View File
@@ -152,13 +152,6 @@ const webExtensionMock = {
getAll: vi.fn().mockResolvedValue([]),
remove: vi.fn().mockResolvedValue(undefined),
},
alarms: {
create: vi.fn().mockResolvedValue(undefined),
onAlarm: {
addListener: vi.fn(),
removeListener: vi.fn(),
},
},
contextMenus: {
create: vi.fn(),
onClicked: {
-1
View File
@@ -56,7 +56,6 @@ export default defineConfig({
'cookies',
'sidePanel',
'contextMenus',
'alarms',
],
host_permissions: ['<all_urls>'],
action: {