/** * 認證來源:預設沿用使用者既有的 `tea login`,不另外要求設定一組 token。 * TEA_SDLC_API_BASE / TEA_SDLC_TOKEN 只是給測試與 CI 的覆寫出口。 */ import test from 'node:test'; import assert from 'node:assert/strict'; import { mkdtempSync, mkdirSync, writeFileSync } from 'node:fs'; import { join } from 'node:path'; import { runScript, tmpRoot } from './helpers/run-script.js'; import { startStubGitea, healthyRoutes } from './helpers/stub-gitea.js'; const REPO = 'plugins/tea-sdlc'; /** 寫一份 tea 風格的 config.yml 到暫存目錄,回傳路徑 */ function writeTeaConfig(logins) { mkdirSync(tmpRoot, { recursive: true }); const dir = mkdtempSync(join(tmpRoot, 'tea-')); const path = join(dir, 'config.yml'); const body = logins .map((l) => [ ` - name: ${l.name}`, ` url: ${l.url}`, ` token: ${l.token}`, ` default: ${l.default ?? false}`, ` ssh_key: ""`, ` user: ${l.user ?? 'tester'}`, ].join('\n'), ) .join('\n'); writeFileSync(path, `logins:\n${body}\npreferences:\n editor: false\n`); return path; } async function withStub(t) { const stub = await startStubGitea(healthyRoutes(REPO)); t.after(() => stub.close()); return stub; } /** stub 的 base 是 .../api/v1,tea config 記的是站台根網址 */ const siteUrl = (stub) => stub.base.replace(/\/api\/v1$/, ''); test('沒有環境變數覆寫時,採用 tea 設定中 default 為真的登入', async (t) => { const stub = await withStub(t); const config = writeTeaConfig([ { name: 'OTHER', url: 'https://gitea.example.com', token: 'wrong-token' }, { name: 'JSC', url: siteUrl(stub), token: 'config-token', default: true }, ]); const { code, json } = await runScript('labels-list.js', ['--repo', REPO], { env: { TEA_SDLC_CONFIG: config }, }); assert.equal(code, 0); assert.equal(json.ok, true); assert.equal(stub.requests[0].authorization, 'token config-token'); }); test('--host 指定站台時,挑出對應的那一組登入', async (t) => { const stub = await withStub(t); const config = writeTeaConfig([ { name: 'JSC', url: siteUrl(stub), token: 'jsc-token' }, { name: 'HP', url: 'https://gitea.example.com', token: 'hp-token', default: true }, ]); const { code, json } = await runScript( 'labels-list.js', ['--repo', REPO, '--host', siteUrl(stub)], { env: { TEA_SDLC_CONFIG: config } }, ); assert.equal(code, 0, JSON.stringify(json)); assert.equal(stub.requests[0].authorization, 'token jsc-token'); }); test('--host 指定的站台沒有對應登入時,明確說是哪個站台缺登入', async (t) => { const config = writeTeaConfig([{ name: 'JSC', url: 'https://gitea.example.com', token: 't', default: true }]); const { code, json } = await runScript( 'labels-list.js', ['--repo', REPO, '--host', 'https://gitea.missing.tw'], { env: { TEA_SDLC_CONFIG: config } }, ); assert.equal(code, 1); assert.equal(json.error.code, 'LOGIN_INVALID'); assert.match(json.error.message, /gitea\.missing\.tw/); }); test('tea 設定檔不存在時,訊息指向 tea login add', async (t) => { const { json } = await runScript('labels-list.js', ['--repo', REPO], { env: { TEA_SDLC_CONFIG: join(tmpRoot, 'definitely-not-here', 'config.yml') }, }); assert.equal(json.error.code, 'LOGIN_INVALID'); assert.match(json.error.message, /tea login add/); }); test('設定檔存在但沒有任何登入時,同樣指向 tea login add', async (t) => { mkdirSync(tmpRoot, { recursive: true }); const dir = mkdtempSync(join(tmpRoot, 'tea-')); const path = join(dir, 'config.yml'); writeFileSync(path, 'logins: []\npreferences:\n editor: false\n'); const { json } = await runScript('labels-list.js', ['--repo', REPO], { env: { TEA_SDLC_CONFIG: path }, }); assert.equal(json.error.code, 'LOGIN_INVALID'); assert.match(json.error.message, /tea login add/); }); test('只有一組登入且未標 default 時,就用那一組', async (t) => { const stub = await withStub(t); const config = writeTeaConfig([{ name: 'ONLY', url: siteUrl(stub), token: 'only-token' }]); const { code } = await runScript('labels-list.js', ['--repo', REPO], { env: { TEA_SDLC_CONFIG: config }, }); assert.equal(code, 0); assert.equal(stub.requests[0].authorization, 'token only-token'); });