agent-ecosystem/test/renderer/utils/fileReferences.test.ts

179 lines
6 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { extractFileReferences } from '@renderer/utils/groupTransformer';
describe('extractFileReferences', () => {
describe('accepts valid file references', () => {
it('accepts paths starting with known directories', () => {
const refs = extractFileReferences('Check @src/components/App.tsx');
expect(refs).toHaveLength(1);
expect(refs[0].path).toBe('src/components/App.tsx');
});
it('accepts utils/ paths (known dir)', () => {
const refs = extractFileReferences('See @utils/helpers');
expect(refs).toHaveLength(1);
expect(refs[0].path).toBe('utils/helpers');
});
it('accepts hooks/ paths (known dir)', () => {
const refs = extractFileReferences('Use @hooks/auth');
expect(refs).toHaveLength(1);
expect(refs[0].path).toBe('hooks/auth');
});
it('accepts lib/ paths (known dir)', () => {
const refs = extractFileReferences('In @lib/core');
expect(refs).toHaveLength(1);
expect(refs[0].path).toBe('lib/core');
});
it('accepts config/ paths (known dir)', () => {
const refs = extractFileReferences('Edit @config/database');
expect(refs).toHaveLength(1);
expect(refs[0].path).toBe('config/database');
});
it('accepts relative paths with ./', () => {
const refs = extractFileReferences('See @./src/file.ts');
expect(refs).toHaveLength(1);
expect(refs[0].path).toBe('./src/file.ts');
});
it('accepts relative paths with ../', () => {
const refs = extractFileReferences('See @../lib/utils.ts');
expect(refs).toHaveLength(1);
expect(refs[0].path).toBe('../lib/utils.ts');
});
it('accepts unknown-dir paths with 3+ segments', () => {
const refs = extractFileReferences('See @custom/deep/path.ts');
expect(refs).toHaveLength(1);
expect(refs[0].path).toBe('custom/deep/path.ts');
});
it('accepts unknown-dir paths with file extension', () => {
const refs = extractFileReferences('See @foo/bar.ts');
expect(refs).toHaveLength(1);
expect(refs[0].path).toBe('foo/bar.ts');
});
it('accepts node_modules paths (known dir)', () => {
const refs = extractFileReferences('Check @node_modules/lodash/index.js');
expect(refs).toHaveLength(1);
expect(refs[0].path).toBe('node_modules/lodash/index.js');
});
it('accepts types/ paths (known dir)', () => {
const refs = extractFileReferences('See @types/node');
expect(refs).toHaveLength(1);
expect(refs[0].path).toBe('types/node');
});
it('extracts multiple references from one string', () => {
const refs = extractFileReferences('Compare @src/a.ts and @lib/b.ts');
expect(refs).toHaveLength(2);
expect(refs[0].path).toBe('src/a.ts');
expect(refs[1].path).toBe('lib/b.ts');
});
it('accepts tilde paths', () => {
const refs = extractFileReferences('See @~/projects/foo');
expect(refs).toHaveLength(1);
expect(refs[0].path).toBe('~/projects/foo');
});
it('accepts Windows backslash paths', () => {
const refs = extractFileReferences('Check @src\\components\\App.tsx');
expect(refs).toHaveLength(1);
expect(refs[0].path).toBe('src\\components\\App.tsx');
});
it('accepts Windows drive absolute paths', () => {
const refs = extractFileReferences('Open @C:\\Users\\Alice\\project\\src\\App.tsx');
expect(refs).toHaveLength(1);
expect(refs[0].path).toBe('C:\\Users\\Alice\\project\\src\\App.tsx');
});
it('accepts quoted paths with spaces', () => {
const refs = extractFileReferences('Open @"src/My Component/App.tsx" now');
expect(refs).toHaveLength(1);
expect(refs[0]).toEqual({
path: 'src/My Component/App.tsx',
raw: '@"src/My Component/App.tsx"',
});
});
});
describe('rejects npm scoped packages', () => {
it('rejects @babel/core', () => {
const refs = extractFileReferences('Use @babel/core for transpilation');
expect(refs).toHaveLength(0);
});
it('rejects @xyflow/react', () => {
const refs = extractFileReferences('Install @xyflow/react');
expect(refs).toHaveLength(0);
});
it('rejects @dagrejs/dagre', () => {
const refs = extractFileReferences('Use @dagrejs/dagre for layout');
expect(refs).toHaveLength(0);
});
it('rejects @testing-library/react', () => {
const refs = extractFileReferences('Import from @testing-library/react');
expect(refs).toHaveLength(0);
});
it('rejects @vitest/ui', () => {
const refs = extractFileReferences('Run @vitest/ui');
expect(refs).toHaveLength(0);
});
it('rejects @radix-ui/react-dialog', () => {
const refs = extractFileReferences('Use @radix-ui/react-dialog');
expect(refs).toHaveLength(0);
});
it('rejects @codemirror/lang-javascript', () => {
const refs = extractFileReferences('Import @codemirror/lang-javascript');
expect(refs).toHaveLength(0);
});
it('rejects @emotion/react', () => {
const refs = extractFileReferences('Style with @emotion/react');
expect(refs).toHaveLength(0);
});
});
describe('edge cases', () => {
it('returns empty for text without @', () => {
const refs = extractFileReferences('No mentions here');
expect(refs).toHaveLength(0);
});
it('returns empty for empty string', () => {
const refs = extractFileReferences('');
expect(refs).toHaveLength(0);
});
it('rejects bare @ mentions without path separator', () => {
const refs = extractFileReferences('Hello @user');
expect(refs).toHaveLength(0);
});
it('handles mixed valid and invalid refs', () => {
const refs = extractFileReferences(
'Use @babel/core and check @src/components/App.tsx'
);
expect(refs).toHaveLength(1);
expect(refs[0].path).toBe('src/components/App.tsx');
});
it('rejects single-segment bare names', () => {
const refs = extractFileReferences('@react is a library');
expect(refs).toHaveLength(0);
});
});
});