mirror of
https://github.com/Silentely/eSIM-Tools.git
synced 2026-09-03 06:24:20 +08:00
🔧 chore(hooks): 提交前同步远程并静默无效URL测试日志
This commit is contained in:
@@ -290,7 +290,7 @@ open tests/test_simyo_esim.html
|
||||
- `📝 docs(readme): 更新安装说明`
|
||||
|
||||
### 当前 Git 钩子
|
||||
- `pre-commit`:提交前格式化 staged 文件,并执行 JS/JSON 语法检查与智能引号拦截
|
||||
- `pre-commit`:提交前先同步远程更新(有 upstream 时自动 `git pull --rebase --autostash`),再格式化 staged 文件并执行 JS/JSON 语法检查与智能引号拦截
|
||||
- `pre-push`:默认快速模式(`pre-commit` + 相关测试),无差异文件时回退全量测试
|
||||
- `prepare-commit-msg`:提交信息为空时自动填充模板
|
||||
- `commit-msg`:校验提交信息格式(emoji + type + 中文描述 + 映射关系)
|
||||
|
||||
@@ -278,7 +278,7 @@ Examples:
|
||||
- `📝 docs(readme): 更新安装说明`
|
||||
|
||||
### Current Git Hooks
|
||||
- `pre-commit`: formats staged files and runs JS/JSON syntax + smart quotes checks
|
||||
- `pre-commit`: syncs remote updates first (auto `git pull --rebase --autostash` when upstream exists), then formats staged files and runs JS/JSON syntax + smart quotes checks
|
||||
- `pre-push`: defaults to fast mode (`pre-commit` + related tests), falls back to full tests when no diff files are detected
|
||||
- `prepare-commit-msg`: auto-fills a template when commit message is empty
|
||||
- `commit-msg`: validates message format (emoji + type + Chinese summary + mapping)
|
||||
|
||||
@@ -71,6 +71,39 @@ function getTouchedProtectedFiles() {
|
||||
return output.split('\0').filter(Boolean);
|
||||
}
|
||||
|
||||
function getUpstreamRef() {
|
||||
try {
|
||||
return git([
|
||||
'rev-parse',
|
||||
'--abbrev-ref',
|
||||
'--symbolic-full-name',
|
||||
'@{u}'
|
||||
]).trim();
|
||||
} catch (_) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function syncWithRemote() {
|
||||
const upstreamRef = getUpstreamRef();
|
||||
if (!upstreamRef) {
|
||||
console.log('ℹ️ 当前分支未配置 upstream,跳过远程同步');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`🔄 提交前同步远程更新(${upstreamRef})...`);
|
||||
try {
|
||||
git(['pull', '--rebase', '--autostash', '--quiet'], {
|
||||
stdio: 'inherit'
|
||||
});
|
||||
console.log('✅ 远程更新同步完成');
|
||||
} catch (_) {
|
||||
console.error('\n❌ pre-commit 远程同步失败:');
|
||||
console.error(' - 请先手动执行 `git pull --rebase` 解决冲突后再提交。');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
function shouldFormat(relPath) {
|
||||
const ext = path.extname(relPath).toLowerCase();
|
||||
if (TEXT_EXTENSIONS.has(ext)) {
|
||||
@@ -191,6 +224,8 @@ function main() {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
syncWithRemote();
|
||||
|
||||
const stagedFiles = getStagedFiles();
|
||||
if (stagedFiles.length === 0) {
|
||||
process.exit(0);
|
||||
|
||||
@@ -8,7 +8,7 @@ describe('Giffgaff OAuthManager', () => {
|
||||
describe('generateCodeVerifier()', () => {
|
||||
it('应该生成有效的 code verifier', () => {
|
||||
const verifier = OAuthManager.generateCodeVerifier();
|
||||
|
||||
|
||||
expect(verifier).toBeDefined();
|
||||
expect(typeof verifier).toBe('string');
|
||||
expect(verifier.length).toBeGreaterThanOrEqual(43);
|
||||
@@ -20,7 +20,7 @@ describe('Giffgaff OAuthManager', () => {
|
||||
it('每次生成的 verifier 应该不同', () => {
|
||||
const verifier1 = OAuthManager.generateCodeVerifier();
|
||||
const verifier2 = OAuthManager.generateCodeVerifier();
|
||||
|
||||
|
||||
expect(verifier1).not.toBe(verifier2);
|
||||
});
|
||||
});
|
||||
@@ -29,7 +29,7 @@ describe('Giffgaff OAuthManager', () => {
|
||||
it('应该从 verifier 生成有效的 challenge', async () => {
|
||||
const verifier = 'test-verifier-string';
|
||||
const challenge = await OAuthManager.generateCodeChallenge(verifier);
|
||||
|
||||
|
||||
expect(challenge).toBeDefined();
|
||||
expect(typeof challenge).toBe('string');
|
||||
// 检查是否为 base64url 编码
|
||||
@@ -40,7 +40,7 @@ describe('Giffgaff OAuthManager', () => {
|
||||
describe('generateState()', () => {
|
||||
it('应该生成有效的 state 参数', () => {
|
||||
const state = OAuthManager.generateState();
|
||||
|
||||
|
||||
expect(state).toBeDefined();
|
||||
expect(typeof state).toBe('string');
|
||||
expect(state.length).toBeGreaterThan(0);
|
||||
@@ -51,7 +51,7 @@ describe('Giffgaff OAuthManager', () => {
|
||||
it('每次生成的 state 应该不同', () => {
|
||||
const state1 = OAuthManager.generateState();
|
||||
const state2 = OAuthManager.generateState();
|
||||
|
||||
|
||||
expect(state1).not.toBe(state2);
|
||||
});
|
||||
});
|
||||
@@ -60,7 +60,7 @@ describe('Giffgaff OAuthManager', () => {
|
||||
it('应该构建正确的授权 URL', async () => {
|
||||
const verifier = 'test-verifier';
|
||||
const url = await OAuthManager.buildAuthorizationUrl(verifier);
|
||||
|
||||
|
||||
expect(url).toContain('https://id.giffgaff.com/oauth/authorize');
|
||||
expect(url).toContain('response_type=code');
|
||||
expect(url).toContain('client_id=');
|
||||
@@ -76,36 +76,42 @@ describe('Giffgaff OAuthManager', () => {
|
||||
it('应该从标准 URL 提取授权码', () => {
|
||||
const callbackUrl = 'https://example.com/callback?code=test-code&state=test-state';
|
||||
const code = OAuthManager.extractCodeFromCallback(callbackUrl);
|
||||
|
||||
|
||||
expect(code).toBe('test-code');
|
||||
});
|
||||
|
||||
it('应该从 giffgaff:// 协议 URL 提取授权码', () => {
|
||||
const callbackUrl = 'giffgaff://auth/callback/?code=test-code&state=test-state';
|
||||
const code = OAuthManager.extractCodeFromCallback(callbackUrl);
|
||||
|
||||
|
||||
expect(code).toBe('test-code');
|
||||
});
|
||||
|
||||
it('应该处理编码的授权码', () => {
|
||||
const callbackUrl = 'https://example.com/callback?code=test%2Bcode%3D&state=test';
|
||||
const code = OAuthManager.extractCodeFromCallback(callbackUrl);
|
||||
|
||||
|
||||
expect(code).toBe('test+code=');
|
||||
});
|
||||
|
||||
it('应该在没有授权码时返回 null', () => {
|
||||
const callbackUrl = 'https://example.com/callback?state=test-state';
|
||||
const code = OAuthManager.extractCodeFromCallback(callbackUrl);
|
||||
|
||||
|
||||
expect(code).toBeNull();
|
||||
});
|
||||
|
||||
it('应该处理无效的 URL', () => {
|
||||
const consoleErrorSpy = jest
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => {});
|
||||
const callbackUrl = 'not-a-valid-url';
|
||||
const code = OAuthManager.extractCodeFromCallback(callbackUrl);
|
||||
|
||||
expect(code).toBeNull();
|
||||
try {
|
||||
const code = OAuthManager.extractCodeFromCallback(callbackUrl);
|
||||
expect(code).toBeNull();
|
||||
} finally {
|
||||
consoleErrorSpy.mockRestore();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -120,14 +126,14 @@ describe('Giffgaff OAuthManager', () => {
|
||||
token_type: 'Bearer',
|
||||
expires_in: 3600
|
||||
};
|
||||
|
||||
|
||||
global.fetch.mockResolvedValueOnce({
|
||||
ok: true,
|
||||
json: async () => mockResponse
|
||||
});
|
||||
|
||||
|
||||
const result = await OAuthManager.exchangeToken('test-code', 'test-verifier');
|
||||
|
||||
|
||||
expect(result).toEqual(mockResponse);
|
||||
expect(global.fetch).toHaveBeenCalledWith(
|
||||
'/.netlify/functions/giffgaff-token-exchange',
|
||||
@@ -145,10 +151,10 @@ describe('Giffgaff OAuthManager', () => {
|
||||
status: 400,
|
||||
text: async () => 'Invalid grant'
|
||||
});
|
||||
|
||||
|
||||
await expect(
|
||||
OAuthManager.exchangeToken('invalid-code', 'test-verifier')
|
||||
).rejects.toThrow('Token exchange failed: 400 - Invalid grant');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user