Files
brain/tools/bash-tokenizer.test.mjs

73 lines
2.2 KiB
JavaScript

import { describe, it, expect } from 'vitest';
import { tokenizeBash, isMutatingSegment } from './bash-tokenizer.mjs';
describe('tokenizeBash — basics', () => {
it('tokenizes a simple command', () => {
const r = tokenizeBash('ls -la /tmp');
expect(r.ok).toBe(true);
expect(r.segments).toHaveLength(1);
expect(r.segments[0].tokens).toEqual(['ls', '-la', '/tmp']);
expect(r.hasSubshell).toBe(false);
});
it('returns ok:false on empty input', () => {
expect(tokenizeBash('').ok).toBe(false);
expect(tokenizeBash(' ').ok).toBe(false);
expect(tokenizeBash(null).ok).toBe(false);
});
});
describe('tokenizeBash — segments & operators', () => {
it('splits on && and records the operator', () => {
const r = tokenizeBash('ls && git commit');
expect(r.segments.map((s) => s.tokens[0])).toEqual(['ls', 'git']);
expect(r.segments[0].op).toBe('&&');
expect(r.segments[1].op).toBe(null);
});
it('splits on pipe', () => {
const r = tokenizeBash('cat a | grep x');
expect(r.segments).toHaveLength(2);
expect(r.segments[0].op).toBe('|');
});
});
describe('tokenizeBash — sub-shell detection', () => {
it.each([
['echo `ls`', 'backtick'],
['echo $(ls)', 'cmd-subst'],
['diff <(ls a) <(ls b)', 'process-subst-in'],
['cat <<EOF\nx\nEOF', 'heredoc'],
])('flags %s', (cmd, kind) => {
const r = tokenizeBash(cmd);
expect(r.ok).toBe(true);
expect(r.hasSubshell).toBe(true);
expect(r.subshellKinds).toContain(kind);
});
it('does not flag plain command', () => {
expect(tokenizeBash('ls -la').hasSubshell).toBe(false);
});
});
describe('tokenizeBash — parse errors', () => {
it('returns ok:false on unbalanced quotes', () => {
expect(tokenizeBash('echo "unterminated').ok).toBe(false);
expect(tokenizeBash("echo 'open").ok).toBe(false);
});
});
describe('isMutatingSegment', () => {
it.each([
[['rm', '-rf', 'x'], true],
[['git', 'commit', '-m', 'x'], true],
[['git', 'status'], false],
[['composer', 'install'], true],
[['composer', 'show'], false],
[['cat', 'x', '>', 'y'], true],
[['grep', 'x', 'file'], false],
])('%j → %s', (tokens, expected) => {
expect(isMutatingSegment(tokens)).toBe(expected);
});
});