Files
binect-chrome/tests/tracker.test.ts
tegwick b09290cb83 Release 0.1: Complete BinectChrome implementation
Implements all requirements from ProductRequirementsDocument.md:
- PDF detection via Chrome Downloads API
- Secure credential storage with AES-GCM encryption
- Binect API integration for PDF uploads
- Popup UI with Binect branding
- Local transfer tracking (500 entry cap)
- Help page with tracking view and CSV export
- 60-day credential retention with auto-expiry
- Accessibility compliance (WCAG 2.1 AA)

Technical implementation:
- Chrome Extension Manifest V3
- TypeScript with strict mode
- Webpack build system
- Jest test suite (22/22 passing)
- ESLint configured (0 errors)

Build output: 13 KB total (production minified)
Test coverage: crypto, pdf-detector, tracker, binect-api

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-13 00:30:39 +01:00

154 lines
4.1 KiB
TypeScript

/**
* Tests for tracking system
*/
import {
addTrackingEntry,
getAllEntries,
getTrackingSummary,
clearTracking,
exportAsCSV
} from '../src/tracking/tracker';
// Mock chrome storage
const mockStorage: { [key: string]: any } = {};
// Setup chrome storage mocks
(chrome.storage.local.get as jest.Mock).mockImplementation((key) => {
return Promise.resolve({ [key]: mockStorage[key] });
});
(chrome.storage.local.set as jest.Mock).mockImplementation((data) => {
Object.assign(mockStorage, data);
return Promise.resolve();
});
(chrome.storage.local.remove as jest.Mock).mockImplementation((key) => {
delete mockStorage[key];
return Promise.resolve();
});
describe('Tracking system', () => {
beforeEach(() => {
// Clear mock storage
Object.keys(mockStorage).forEach((key) => delete mockStorage[key]);
jest.clearAllMocks();
});
test('should add tracking entry', async () => {
await addTrackingEntry({
timestamp: Date.now(),
sourceDomain: 'example.com',
destinationUrl: 'https://api.binect.de/upload',
pdfSize: 1024,
result: 'success'
});
const entries = await getAllEntries();
expect(entries.length).toBe(1);
expect(entries[0].sourceDomain).toBe('example.com');
expect(entries[0].result).toBe('success');
});
test('should maintain max entries limit', async () => {
// Add 501 entries
for (let i = 0; i < 501; i++) {
await addTrackingEntry({
timestamp: Date.now(),
sourceDomain: `example${i}.com`,
destinationUrl: 'https://api.binect.de/upload',
pdfSize: 1024,
result: 'success'
});
}
const entries = await getAllEntries();
expect(entries.length).toBe(500); // Should be capped at 500
expect(entries[0].sourceDomain).toBe('example500.com'); // Most recent first
});
test('should calculate tracking summary correctly', async () => {
await addTrackingEntry({
timestamp: Date.now(),
sourceDomain: 'example.com',
destinationUrl: 'https://api.binect.de/upload',
pdfSize: 1024,
result: 'success'
});
await addTrackingEntry({
timestamp: Date.now(),
sourceDomain: 'example2.com',
destinationUrl: 'https://api.binect.de/upload',
pdfSize: 2048,
result: 'failure',
errorMessage: 'Network error'
});
const summary = await getTrackingSummary();
expect(summary.totalTransfers).toBe(2);
expect(summary.successfulTransfers).toBe(1);
expect(summary.failedTransfers).toBe(1);
expect(summary.lastTransferTime).toBeDefined();
});
test('should export to CSV correctly', () => {
const entries = [
{
id: '1',
timestamp: 1640000000000,
sourceDomain: 'example.com',
destinationUrl: 'https://api.binect.de/upload',
pdfSize: 1024,
result: 'success' as const
},
{
id: '2',
timestamp: 1640000001000,
sourceDomain: 'test.com',
destinationUrl: 'https://api.binect.de/upload',
pdfSize: 2048,
result: 'failure' as const,
errorMessage: 'Network error'
}
];
const csv = exportAsCSV(entries);
expect(csv).toContain('Timestamp,Source Domain,Destination URL');
expect(csv).toContain('example.com');
expect(csv).toContain('test.com');
expect(csv).toContain('Network error');
});
test('should handle CSV escaping', () => {
const entries = [
{
id: '1',
timestamp: 1640000000000,
sourceDomain: 'example,with,commas.com',
destinationUrl: 'https://api.binect.de/upload',
pdfSize: 1024,
result: 'success' as const
}
];
const csv = exportAsCSV(entries);
expect(csv).toContain('"example,with,commas.com"');
});
test('should clear tracking data', async () => {
await addTrackingEntry({
timestamp: Date.now(),
sourceDomain: 'example.com',
destinationUrl: 'https://api.binect.de/upload',
pdfSize: 1024,
result: 'success'
});
await clearTracking();
const entries = await getAllEntries();
expect(entries.length).toBe(0);
});
});