This document describes the refactored, testable feed processing utilities and how to run tests.
The feed processing logic has been extracted into small, testable functions in src/lib/:
articleUtils.js- Pure functions for article hashing and scoring (no external dependencies)feedUtils.js- Utility functions for feed processing (headers, Redis keys, validation, etc.)
node src/lib/feedUtils.test.jsAll tests use the test data in testdata/test-cases.json which contains expected inputs and outputs generated from the actual Node.js implementation.
-
hash(article)- MD5 hash of article GUID- Tests: 3 test cases verifying hash consistency
- Implementation matches
src/articles.jsexactly
-
score(article)- Unix timestamp score- Tests: 3 test cases with different date field names (pubDate, pubdate, date)
- Implementation matches
src/articles.jsexactly
-
buildRequestHeaders(storedFeed)- Builds HTTP headers for conditional GET- Tests: 4 test cases (no headers, If-Modified-Since, If-None-Match, both)
-
buildRedisKeys(feedURI)- Creates Redis key names- Tests: 2 test cases with different feed URLs
-
buildArticleKey(hash)- Creates article key for Redis sorted set- Tests: 1 test case verifying format
-
processArticle(article, feedURI, hashFn, scoreFn)- Adds computed fields- Tests: 1 test case verifying hash, score, and feedurl are added
-
shouldStoreArticle(oldScore, newScore)- Determines if article needs S3 storage- Tests: 4 test cases (new article, changed score, unchanged score, type coercion)
-
isValidArticle(article)- Validates article has required fields- Tests: 4 test cases (valid, missing guid, missing description, null)
-
extractFeedMetadata(meta)- Extracts title and link from parser meta- Tests: 1 test case
-
extractArticleIds(articleKeys)- Strips "article:" prefix from Redis keys- Tests: 1 test case
The testdata/test-cases.json file contains test cases organized by function:
{
"hash_function_tests": [...],
"score_function_tests": [...],
"request_headers_tests": [...],
...
}Each test case has:
description- Human-readable test descriptioninput- Input value(s) for the functionexpected- Expected output value
- Add test data to
testdata/test-cases.json - Add corresponding test code in
src/lib/feedUtils.test.js - Run tests to verify
Next steps:
- Refactor
src/feeds.jsto use these utility functions - Add integration tests for Redis and S3 operations
- Create Go implementation with matching behavior (in
feedfetcher/directory) - Create Go tests that use the same
testdata/test-cases.jsonfile
These functions were extracted because they are:
- Pure or nearly pure - Deterministic output for given input
- Core business logic - Critical for feed processing correctness
- Reusable - Can be used by both Node.js and Go implementations
- Independently testable - No mocking of Redis/S3 needed
The goal is to ensure both Node.js and Go implementations produce identical results for:
- Article hashing (critical for deduplication)
- Article scoring (critical for sorting)
- Request headers (critical for conditional GET optimization)
- Redis key naming (critical for data storage)
- S3 storage decisions (critical for performance)