feat: implement v2 3-tier architecture (mcpctl → mcplocal → mcpd)
- Rename local-proxy to mcplocal with HTTP server, LLM pipeline, mcpd discovery - Add LLM pre-processing: token estimation, filter cache, metrics, Gemini CLI + DeepSeek providers - Add mcpd auth (login/logout) and MCP proxy endpoints - Update CLI: dual URLs (mcplocalUrl/mcpdUrl), auth commands, --direct flag - Add tiered health monitoring, shell completions, e2e integration tests - 57 test files, 597 tests passing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
59
src/cli/tests/auth/credentials.test.ts
Normal file
59
src/cli/tests/auth/credentials.test.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||
import { mkdtempSync, rmSync, statSync, existsSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { saveCredentials, loadCredentials, deleteCredentials } from '../../src/auth/index.js';
|
||||
|
||||
let tempDir: string;
|
||||
|
||||
beforeEach(() => {
|
||||
tempDir = mkdtempSync(join(tmpdir(), 'mcpctl-auth-test-'));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
rmSync(tempDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
describe('saveCredentials', () => {
|
||||
it('saves credentials file', () => {
|
||||
saveCredentials({ token: 'tok123', mcpdUrl: 'http://x:3100', user: 'alice@test.com' }, { configDir: tempDir });
|
||||
expect(existsSync(join(tempDir, 'credentials'))).toBe(true);
|
||||
});
|
||||
|
||||
it('sets 0600 permissions', () => {
|
||||
saveCredentials({ token: 'tok123', mcpdUrl: 'http://x:3100', user: 'alice@test.com' }, { configDir: tempDir });
|
||||
const stat = statSync(join(tempDir, 'credentials'));
|
||||
expect(stat.mode & 0o777).toBe(0o600);
|
||||
});
|
||||
|
||||
it('creates config dir if missing', () => {
|
||||
const nested = join(tempDir, 'sub', 'dir');
|
||||
saveCredentials({ token: 'tok', mcpdUrl: 'http://x:3100', user: 'bob' }, { configDir: nested });
|
||||
expect(existsSync(join(nested, 'credentials'))).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadCredentials', () => {
|
||||
it('returns null when no credentials file', () => {
|
||||
expect(loadCredentials({ configDir: tempDir })).toBeNull();
|
||||
});
|
||||
|
||||
it('round-trips credentials', () => {
|
||||
const creds = { token: 'tok456', mcpdUrl: 'http://remote:3100', user: 'charlie@test.com', expiresAt: '2099-01-01' };
|
||||
saveCredentials(creds, { configDir: tempDir });
|
||||
const loaded = loadCredentials({ configDir: tempDir });
|
||||
expect(loaded).toEqual(creds);
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteCredentials', () => {
|
||||
it('returns false when no credentials file', () => {
|
||||
expect(deleteCredentials({ configDir: tempDir })).toBe(false);
|
||||
});
|
||||
|
||||
it('deletes credentials file', () => {
|
||||
saveCredentials({ token: 'tok', mcpdUrl: 'http://x:3100', user: 'u' }, { configDir: tempDir });
|
||||
expect(deleteCredentials({ configDir: tempDir })).toBe(true);
|
||||
expect(existsSync(join(tempDir, 'credentials'))).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user