mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-28 11:41:04 +00:00
* docs: update quota exceeded alternatives to OpenRouter and Fireworks - Update README.md news section to recommend OpenRouter and Fireworks as primary alternatives, with ModelStudio as third option - Update retry.ts quota error message to include OpenRouter and Fireworks URLs for users whose OAuth quota has been exhausted Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(test): update retry test assertions to match new quota error message * docs: update free tier quota to 100 req/day with sunset notice and alternatives Update all references to reflect the Qwen OAuth free tier policy change: - 1,000 → 100 requests/day across code, i18n, and docs - Add 2026-04-15 sunset date everywhere - Guide users to OpenRouter, Fireworks AI, or ModelStudio in docs - Remove CHANGELOG.md --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Co-authored-by: tanzhenxin <tanzhenxing1987@gmail.com>
266 lines
6.8 KiB
TypeScript
266 lines
6.8 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
import { showAuthStatus } from './handler.js';
|
|
import { AuthType } from '@qwen-code/qwen-code-core';
|
|
import { CODING_PLAN_ENV_KEY } from '../../constants/codingPlan.js';
|
|
import type { LoadedSettings } from '../../config/settings.js';
|
|
|
|
vi.mock('../../config/settings.js', () => ({
|
|
loadSettings: vi.fn(),
|
|
}));
|
|
|
|
vi.mock('../../utils/stdioHelpers.js', () => ({
|
|
writeStdoutLine: vi.fn(),
|
|
writeStderrLine: vi.fn(),
|
|
}));
|
|
|
|
import { loadSettings } from '../../config/settings.js';
|
|
import { writeStdoutLine, writeStderrLine } from '../../utils/stdioHelpers.js';
|
|
|
|
describe('showAuthStatus', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
vi.spyOn(process, 'exit').mockImplementation((() => undefined) as never);
|
|
delete process.env[CODING_PLAN_ENV_KEY];
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks();
|
|
delete process.env[CODING_PLAN_ENV_KEY];
|
|
});
|
|
|
|
const createMockSettings = (
|
|
merged: Record<string, unknown>,
|
|
): LoadedSettings =>
|
|
({
|
|
merged,
|
|
system: { settings: {}, path: '/system.json' },
|
|
systemDefaults: { settings: {}, path: '/system-defaults.json' },
|
|
user: { settings: {}, path: '/user.json' },
|
|
workspace: { settings: {}, path: '/workspace.json' },
|
|
forScope: vi.fn(),
|
|
setValue: vi.fn(),
|
|
isTrusted: true,
|
|
}) as unknown as LoadedSettings;
|
|
|
|
it('should show message when no authentication is configured', async () => {
|
|
vi.mocked(loadSettings).mockReturnValue(createMockSettings({}));
|
|
|
|
await showAuthStatus();
|
|
|
|
expect(writeStdoutLine).toHaveBeenCalledWith(
|
|
expect.stringContaining('No authentication method configured'),
|
|
);
|
|
expect(writeStdoutLine).toHaveBeenCalledWith(
|
|
expect.stringContaining('qwen auth qwen-oauth'),
|
|
);
|
|
expect(writeStdoutLine).toHaveBeenCalledWith(
|
|
expect.stringContaining('qwen auth coding-plan'),
|
|
);
|
|
expect(process.exit).toHaveBeenCalledWith(0);
|
|
});
|
|
|
|
it('should show Qwen OAuth status when configured', async () => {
|
|
vi.mocked(loadSettings).mockReturnValue(
|
|
createMockSettings({
|
|
security: {
|
|
auth: {
|
|
selectedType: AuthType.QWEN_OAUTH,
|
|
},
|
|
},
|
|
}),
|
|
);
|
|
|
|
await showAuthStatus();
|
|
|
|
expect(writeStdoutLine).toHaveBeenCalledWith(
|
|
expect.stringContaining('Qwen OAuth'),
|
|
);
|
|
expect(writeStdoutLine).toHaveBeenCalledWith(
|
|
expect.stringContaining('Free tier (ending 2026-04-15)'),
|
|
);
|
|
expect(writeStdoutLine).toHaveBeenCalledWith(
|
|
expect.stringContaining('100 requests/day'),
|
|
);
|
|
expect(process.exit).toHaveBeenCalledWith(0);
|
|
});
|
|
|
|
it('should show Coding Plan status when configured with API key', async () => {
|
|
process.env[CODING_PLAN_ENV_KEY] = 'test-api-key';
|
|
|
|
vi.mocked(loadSettings).mockReturnValue(
|
|
createMockSettings({
|
|
security: {
|
|
auth: {
|
|
selectedType: AuthType.USE_OPENAI,
|
|
},
|
|
},
|
|
codingPlan: {
|
|
region: 'china',
|
|
version: 'abc123def456',
|
|
},
|
|
model: {
|
|
name: 'qwen3.5-plus',
|
|
},
|
|
}),
|
|
);
|
|
|
|
await showAuthStatus();
|
|
|
|
expect(writeStdoutLine).toHaveBeenCalledWith(
|
|
expect.stringContaining('Alibaba Cloud Coding Plan'),
|
|
);
|
|
expect(writeStdoutLine).toHaveBeenCalledWith(
|
|
expect.stringContaining('API key configured'),
|
|
);
|
|
expect(process.exit).toHaveBeenCalledWith(0);
|
|
});
|
|
|
|
it('should show Coding Plan as incomplete when API key is missing', async () => {
|
|
vi.mocked(loadSettings).mockReturnValue(
|
|
createMockSettings({
|
|
security: {
|
|
auth: {
|
|
selectedType: AuthType.USE_OPENAI,
|
|
},
|
|
},
|
|
codingPlan: {
|
|
region: 'global',
|
|
},
|
|
}),
|
|
);
|
|
|
|
await showAuthStatus();
|
|
|
|
expect(writeStdoutLine).toHaveBeenCalledWith(
|
|
expect.stringContaining('Incomplete'),
|
|
);
|
|
expect(writeStdoutLine).toHaveBeenCalledWith(
|
|
expect.stringContaining('API key not found'),
|
|
);
|
|
});
|
|
|
|
it('should show Coding Plan region for china', async () => {
|
|
process.env[CODING_PLAN_ENV_KEY] = 'test-api-key';
|
|
|
|
vi.mocked(loadSettings).mockReturnValue(
|
|
createMockSettings({
|
|
security: {
|
|
auth: {
|
|
selectedType: AuthType.USE_OPENAI,
|
|
},
|
|
},
|
|
codingPlan: {
|
|
region: 'china',
|
|
},
|
|
model: {
|
|
name: 'qwen3.5-plus',
|
|
},
|
|
}),
|
|
);
|
|
|
|
await showAuthStatus();
|
|
|
|
expect(writeStdoutLine).toHaveBeenCalledWith(
|
|
expect.stringContaining('中国 (China)'),
|
|
);
|
|
});
|
|
|
|
it('should show Coding Plan region for global', async () => {
|
|
process.env[CODING_PLAN_ENV_KEY] = 'test-api-key';
|
|
|
|
vi.mocked(loadSettings).mockReturnValue(
|
|
createMockSettings({
|
|
security: {
|
|
auth: {
|
|
selectedType: AuthType.USE_OPENAI,
|
|
},
|
|
},
|
|
codingPlan: {
|
|
region: 'global',
|
|
},
|
|
model: {
|
|
name: 'qwen3-coder-plus',
|
|
},
|
|
}),
|
|
);
|
|
|
|
await showAuthStatus();
|
|
|
|
expect(writeStdoutLine).toHaveBeenCalledWith(
|
|
expect.stringContaining('Global'),
|
|
);
|
|
});
|
|
|
|
it('should show current model name', async () => {
|
|
process.env[CODING_PLAN_ENV_KEY] = 'test-api-key';
|
|
|
|
vi.mocked(loadSettings).mockReturnValue(
|
|
createMockSettings({
|
|
security: {
|
|
auth: {
|
|
selectedType: AuthType.USE_OPENAI,
|
|
},
|
|
},
|
|
codingPlan: {
|
|
region: 'china',
|
|
},
|
|
model: {
|
|
name: 'qwen3.5-plus',
|
|
},
|
|
}),
|
|
);
|
|
|
|
await showAuthStatus();
|
|
|
|
expect(writeStdoutLine).toHaveBeenCalledWith(
|
|
expect.stringContaining('qwen3.5-plus'),
|
|
);
|
|
});
|
|
|
|
it('should show config version (truncated)', async () => {
|
|
process.env[CODING_PLAN_ENV_KEY] = 'test-api-key';
|
|
|
|
vi.mocked(loadSettings).mockReturnValue(
|
|
createMockSettings({
|
|
security: {
|
|
auth: {
|
|
selectedType: AuthType.USE_OPENAI,
|
|
},
|
|
},
|
|
codingPlan: {
|
|
region: 'china',
|
|
version: 'abc123def456789',
|
|
},
|
|
model: {
|
|
name: 'qwen3.5-plus',
|
|
},
|
|
}),
|
|
);
|
|
|
|
await showAuthStatus();
|
|
|
|
expect(writeStdoutLine).toHaveBeenCalledWith(
|
|
expect.stringContaining('abc123de...'),
|
|
);
|
|
});
|
|
|
|
it('should handle errors and exit with code 1', async () => {
|
|
const error = new Error('Settings load failed');
|
|
vi.mocked(loadSettings).mockImplementation(() => {
|
|
throw error;
|
|
});
|
|
|
|
await showAuthStatus();
|
|
|
|
expect(writeStderrLine).toHaveBeenCalledWith(
|
|
expect.stringContaining('Failed to check authentication status'),
|
|
);
|
|
expect(process.exit).toHaveBeenCalledWith(1);
|
|
});
|
|
});
|