98 lines
3 KiB
TypeScript
98 lines
3 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
|
|
import {
|
|
buildTaskLinkHref,
|
|
linkifyTaskIdsInMarkdown,
|
|
parseTaskLinkHref,
|
|
} from '@renderer/utils/taskReferenceUtils';
|
|
|
|
import type { TaskRef } from '@shared/types';
|
|
|
|
describe('taskReferenceUtils', () => {
|
|
describe('TASK_REF_REGEX and isAllowedTaskRefBoundary', () => {
|
|
it('linkifies #ref when preceded by boundary (space, start)', () => {
|
|
const taskRef: TaskRef = {
|
|
taskId: 't1',
|
|
displayId: 'task-1',
|
|
teamName: 'my-team',
|
|
};
|
|
const r = linkifyTaskIdsInMarkdown('see #task-1 done', [taskRef]);
|
|
expect(r).toContain('task://');
|
|
expect(r).toContain('[#task-1]');
|
|
});
|
|
|
|
it('does NOT linkify #ref when preceded by word char', () => {
|
|
const taskRef: TaskRef = {
|
|
taskId: 't1',
|
|
displayId: 'task1',
|
|
teamName: 'my-team',
|
|
};
|
|
const r = linkifyTaskIdsInMarkdown('x#task1', [taskRef]);
|
|
expect(r).toBe('x#task1');
|
|
});
|
|
|
|
it('linkifies #ref with hyphen in id', () => {
|
|
const r = linkifyTaskIdsInMarkdown(' #abc-123 ');
|
|
expect(r).toContain('task://');
|
|
});
|
|
|
|
it('linkifies standalone task refs wrapped in inline code', () => {
|
|
const taskRef: TaskRef = {
|
|
taskId: 'task-1',
|
|
displayId: 'aa5d608e',
|
|
teamName: 'my-team',
|
|
};
|
|
const r = linkifyTaskIdsInMarkdown('done `#aa5d608e`', [taskRef]);
|
|
expect(r).toBe(
|
|
'done [#aa5d608e](task://task-1?team=my-team&display=aa5d608e)'
|
|
);
|
|
});
|
|
|
|
it('does not linkify non-task inline code', () => {
|
|
const r = linkifyTaskIdsInMarkdown('avoid `eval` and `x#task1`');
|
|
expect(r).toBe('avoid `eval` and `x#task1`');
|
|
});
|
|
|
|
it('does not rewrite existing markdown links', () => {
|
|
const existing = '[#aa5d608e](task://aa5d608e)';
|
|
const r = linkifyTaskIdsInMarkdown(existing);
|
|
expect(r).toBe(existing);
|
|
});
|
|
|
|
it('does not linkify task-looking text in fenced code blocks', () => {
|
|
const r = linkifyTaskIdsInMarkdown('```\n#aa5d608e\n```\n#bb7c9012');
|
|
expect(r).toBe('```\n#aa5d608e\n```\n[#bb7c9012](task://bb7c9012)');
|
|
});
|
|
});
|
|
|
|
describe('buildTaskLinkHref and parseTaskLinkHref', () => {
|
|
it('roundtrips task ref', () => {
|
|
const ref: TaskRef = {
|
|
taskId: 'tid-1',
|
|
displayId: 'T-1',
|
|
teamName: 'team-a',
|
|
};
|
|
const href = buildTaskLinkHref(ref);
|
|
expect(href).toContain('task://');
|
|
expect(href).toContain('team=');
|
|
expect(href).toContain('display=');
|
|
|
|
const parsed = parseTaskLinkHref(href);
|
|
expect(parsed).toEqual({
|
|
taskId: 'tid-1',
|
|
teamName: 'team-a',
|
|
displayId: 'T-1',
|
|
});
|
|
});
|
|
|
|
it('parseTaskLinkHref returns null for non-task URL', () => {
|
|
expect(parseTaskLinkHref('https://example.com')).toBeNull();
|
|
expect(parseTaskLinkHref('mention://x')).toBeNull();
|
|
});
|
|
|
|
it('parseTaskLinkHref handles task:// without query', () => {
|
|
const r = parseTaskLinkHref('task://tid-1');
|
|
expect(r).toEqual({ taskId: 'tid-1' });
|
|
});
|
|
});
|
|
});
|