9b395f5cc3
Build Chrome Extension / build (push) Waiting to run
Trigger Website Rebuild (Docs Updated) / dispatch (push) Waiting to run
E2E Headed Chrome / e2e-headed (macos-15) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (ubuntu-latest) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (windows-latest) (push) Has been cancelled
CI / build (macos-latest) (push) Has been cancelled
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
CI / unit-test (push) Has been cancelled
CI / bun-test (push) Has been cancelled
CI / adapter-test (push) Has been cancelled
CI / smoke-test (macos-latest) (push) Has been cancelled
CI / smoke-test (ubuntu-latest) (push) Has been cancelled
Security Audit / audit (push) Has been cancelled
82 lines
2.9 KiB
JavaScript
82 lines
2.9 KiB
JavaScript
import { describe, expect, it } from 'vitest';
|
|
import { getRegistry } from '@jackwener/opencli/registry';
|
|
import './timeline.js';
|
|
const { parseMetric, buildPostId, mergeTimelinePosts } = await import('./timeline.js').then((m) => m.__test__);
|
|
describe('linkedin timeline adapter', () => {
|
|
const command = getRegistry().get('linkedin/timeline');
|
|
it('registers the command with correct shape', () => {
|
|
expect(command).toBeDefined();
|
|
expect(command.site).toBe('linkedin');
|
|
expect(command.name).toBe('timeline');
|
|
expect(command.domain).toBe('www.linkedin.com');
|
|
expect(command.strategy).toBe('cookie');
|
|
expect(command.browser).toBe(true);
|
|
expect(typeof command.func).toBe('function');
|
|
});
|
|
it('has limit arg with default 20', () => {
|
|
const limitArg = command.args.find((a) => a.name === 'limit');
|
|
expect(limitArg).toBeDefined();
|
|
expect(limitArg.default).toBe(20);
|
|
});
|
|
it('includes expected columns', () => {
|
|
expect(command.columns).toEqual(expect.arrayContaining(['author', 'text', 'reactions', 'comments', 'url']));
|
|
});
|
|
});
|
|
describe('parseMetric', () => {
|
|
it('parses plain numbers', () => {
|
|
expect(parseMetric('42')).toBe(42);
|
|
expect(parseMetric('1,234')).toBe(1234);
|
|
});
|
|
it('handles k/m suffixes', () => {
|
|
expect(parseMetric('2.5k')).toBe(2500);
|
|
expect(parseMetric('1.2M')).toBe(1200000);
|
|
});
|
|
it('returns 0 for empty/undefined', () => {
|
|
expect(parseMetric('')).toBe(0);
|
|
expect(parseMetric(undefined)).toBe(0);
|
|
expect(parseMetric(null)).toBe(0);
|
|
});
|
|
});
|
|
describe('buildPostId', () => {
|
|
it('uses url when present', () => {
|
|
expect(buildPostId({ url: 'https://linkedin.com/post/123' })).toBe('https://linkedin.com/post/123');
|
|
});
|
|
it('falls back to composite key', () => {
|
|
const id = buildPostId({ author: 'Alice', posted_at: '2h', text: 'Hello world' });
|
|
expect(id).toBe('Alice::2h::Hello world');
|
|
});
|
|
});
|
|
describe('mergeTimelinePosts', () => {
|
|
it('deduplicates by url', () => {
|
|
const url = 'https://linkedin.com/post/1';
|
|
const a = {
|
|
id: url,
|
|
author: 'Alice',
|
|
author_url: '',
|
|
headline: '',
|
|
text: 'Hello',
|
|
posted_at: '1h',
|
|
reactions: 5,
|
|
comments: 1,
|
|
url,
|
|
};
|
|
const result = mergeTimelinePosts([a], [a]);
|
|
expect(result).toHaveLength(1);
|
|
});
|
|
it('skips posts without author or text', () => {
|
|
const empty = {
|
|
id: '2',
|
|
author: '',
|
|
author_url: '',
|
|
headline: '',
|
|
text: 'some text',
|
|
posted_at: '',
|
|
reactions: 0,
|
|
comments: 0,
|
|
url: '',
|
|
};
|
|
const result = mergeTimelinePosts([], [empty]);
|
|
expect(result).toHaveLength(0);
|
|
});
|
|
});
|