test/dashboard-batch-import-parser.test.js
Rama master · réplica de lectura del repositorio original.
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { BatchImportParseError, parseBatchImportInput } from '../src/dashboard/import-parser.js';
function parseProxyUrl(proxy) {
const s = String(proxy || '').trim();
if (/^\w+:\/\//.test(s)) return { type: 'http', host: 'proxy.example.com', port: 8080 };
if (/^[^:\s]+:\d+$/.test(s)) return { type: 'http', host: s.split(':')[0], port: Number(s.split(':')[1]) };
return null;
}
describe('parseBatchImportInput text mode', () => {
it('supports multiple separators without breaking old whitespace format', () => {
const input = [
'alpha@example.com pass123',
'beta@example.com pass456',
'gamma@example.com\tpass789',
'delta@example.com----pass000',
'echo@example.com|pass111',
'foxtrot@example.com,pass222',
'golf@example.com:pass333',
].join('\n');
const parsed = parseBatchImportInput(input, parseProxyUrl);
assert.equal(parsed.mode, 'text');
assert.equal(parsed.items.length, 7);
assert.deepEqual(
parsed.items.map(item => item.kind),
Array(7).fill('email_password')
);
assert.deepEqual(
parsed.items.map(item => item.password),
['pass123', 'pass456', 'pass789', 'pass000', 'pass111', 'pass222', 'pass333']
);
});
it('supports Chinese and key-value labels copied from chat transcripts', () => {
const input = [
'邮箱:alpha@example.com 密码:pass123',
'邮箱: beta@example.com 密码: pass456',
'email=gamma@example.com password=pass789',
'http://proxy.example.com:8080 邮箱:delta@example.com 密码:pass000',
].join('\n');
const parsed = parseBatchImportInput(input, parseProxyUrl);
assert.equal(parsed.mode, 'text');
assert.equal(parsed.items.length, 4);
assert.deepEqual(
parsed.items.map(item => item.email),
['alpha@example.com', 'beta@example.com', 'gamma@example.com', 'delta@example.com']
);
assert.deepEqual(
parsed.items.map(item => item.password),
['pass123', 'pass456', 'pass789', 'pass000']
);
assert.equal(parsed.items[3].proxyRaw, 'http://proxy.example.com:8080');
});
it('keeps parsing valid lines when one line is invalid', () => {
const parsed = parseBatchImportInput(
'https://proxy.example.com:8080 user1@example.com pass1\ninvalid-line\nuser2@example.com:pass2',
parseProxyUrl
);
assert.equal(parsed.items.length, 3);
assert.equal(parsed.items[0].kind, 'email_password');
assert.equal(parsed.items[0].proxyRaw, 'https://proxy.example.com:8080');
assert.equal(parsed.items[1].kind, 'issue');
assert.equal(parsed.items[1].error, 'ERR_FORMAT_INVALID');
assert.equal(parsed.items[2].kind, 'email_password');
assert.equal(parsed.items[2].password, 'pass2');
});
});
describe('parseBatchImportInput json mode', () => {
it('supports arrays, wrappers, token aliases, and api key aliases', () => {
const payload = JSON.stringify({
accounts: [
{ email: 'one@example.com', password: 'pass1' },
{ username: 'two@example.com', token: 'tok-2', proxy: 'http://proxy.example.com:8080' },
{ account: 'three@example.com', access_token: 'tok-3' },
{ email: 'four@example.com', api_key: 'key-4' },
{ items: 'not-used' },
],
});
const parsed = parseBatchImportInput(payload, parseProxyUrl);
assert.equal(parsed.mode, 'json');
assert.equal(parsed.items.length, 5);
assert.equal(parsed.items[0].kind, 'email_password');
assert.equal(parsed.items[1].kind, 'token');
assert.equal(parsed.items[1].proxyRaw, 'http://proxy.example.com:8080');
assert.equal(parsed.items[2].kind, 'token');
assert.equal(parsed.items[3].kind, 'api_key');
assert.equal(parsed.items[4].kind, 'issue');
assert.equal(parsed.items[4].error, 'ERR_UNSUPPORTED_IMPORT_ITEM');
});
it('supports single-object payloads and throws on invalid json', () => {
const single = parseBatchImportInput(
JSON.stringify({ email: 'solo@example.com', pass: 'secret' }),
parseProxyUrl
);
assert.equal(single.items.length, 1);
assert.equal(single.items[0].kind, 'email_password');
assert.throws(
() => parseBatchImportInput('{"broken"', parseProxyUrl),
(error) => error instanceof BatchImportParseError && error.code === 'ERR_JSON_INVALID'
);
});
it('supports exported Windsurf credential objects', () => {
const payload = JSON.stringify([
{
github_email: 'exported@example.com',
windsurf_api_key: 'ws-key-123',
windsurf_api_server_url: 'https://server.self-serve.windsurf.com',
},
{
windsurf_auth_token: 'windsurf-auth-token',
windsurf_auth_status_raw: {
email: 'fallback@example.com',
apiServerUrl: 'https://server.codeium.com',
},
},
]);
const parsed = parseBatchImportInput(payload, parseProxyUrl);
assert.equal(parsed.mode, 'json');
assert.equal(parsed.items.length, 2);
assert.equal(parsed.items[0].kind, 'api_key');
assert.equal(parsed.items[0].email, 'exported@example.com');
assert.equal(parsed.items[0].apiServerUrl, 'https://server.self-serve.windsurf.com');
assert.equal(parsed.items[1].kind, 'token');
assert.equal(parsed.items[1].email, 'fallback@example.com');
assert.equal(parsed.items[1].apiServerUrl, 'https://server.codeium.com');
});
});