89 lines
2.4 KiB
JavaScript
89 lines
2.4 KiB
JavaScript
import { readFile } from 'node:fs/promises'
|
|
import path from 'node:path'
|
|
import { PassThrough } from 'node:stream'
|
|
import { fileURLToPath } from 'node:url'
|
|
import test from 'brittle'
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor
|
|
|
|
async function loadLoginBin() {
|
|
const runtime = await readFile(path.join(__dirname, '../lib/runtime.js'), 'utf8')
|
|
const preamble = await readFile(
|
|
path.join(__dirname, '../lib/edit/interactive-masked-line.js'),
|
|
'utf8'
|
|
)
|
|
const body = await readFile(path.join(__dirname, '../src/login.js'), 'utf8')
|
|
return new AsyncFunction(
|
|
'ctx',
|
|
'argv',
|
|
`${runtime}\n${preamble}\n${body}\nif (typeof run === 'function') return await run(ctx, argv)\n`
|
|
)
|
|
}
|
|
|
|
function mockTtyStreams() {
|
|
const stdin = new PassThrough()
|
|
stdin.isTTY = true
|
|
stdin.setRawMode = () => {}
|
|
const stdout = new PassThrough()
|
|
return { stdin, stdout }
|
|
}
|
|
|
|
test('login rejects passphrase on argv', async (t) => {
|
|
const run = await loadLoginBin()
|
|
const logs = []
|
|
const errs = []
|
|
const ctx = {
|
|
console: {
|
|
log: () => {},
|
|
error: (m) => errs.push(String(m))
|
|
},
|
|
exitCode: 0,
|
|
applyRegister: async () => {},
|
|
applyUnlock: async () => {
|
|
logs.push('should-not')
|
|
}
|
|
}
|
|
await run(ctx, ['login', 'secret'])
|
|
t.is(logs.length, 0)
|
|
t.is(ctx.exitCode, 1)
|
|
t.ok(errs.some((e) => e.includes('must not be given on the command line')))
|
|
})
|
|
|
|
test('login prompts via TTY streams (masked path)', async (t) => {
|
|
const run = await loadLoginBin()
|
|
let unlocked = ''
|
|
const { stdin, stdout } = mockTtyStreams()
|
|
const ctx = {
|
|
console: { log: () => {}, error: () => {} },
|
|
exitCode: 0,
|
|
stdin,
|
|
stdout,
|
|
suspendReplForSubprocess() {},
|
|
resumeReplAfterSubprocess() {},
|
|
applyRegister: async () => {},
|
|
applyUnlock: async (p) => {
|
|
unlocked = p
|
|
}
|
|
}
|
|
const p = run(ctx, ['login'])
|
|
await new Promise((r) => setImmediate(r))
|
|
stdin.write('two words')
|
|
stdin.write('\n')
|
|
await p
|
|
t.is(unlocked, 'two words')
|
|
t.is(ctx.exitCode, 0)
|
|
})
|
|
|
|
test('login --help', async (t) => {
|
|
const run = await loadLoginBin()
|
|
const logs = []
|
|
const ctx = {
|
|
console: { log: (m) => logs.push(String(m)), error: () => {} },
|
|
exitCode: 1
|
|
}
|
|
await run(ctx, ['login', '--help'])
|
|
t.is(ctx.exitCode, 0)
|
|
t.ok(logs.join('\n').includes('several words'))
|
|
})
|