Testing Strategy
Relevant source files
The following files were used as context for generating this wiki page:The testing strategy for the nodejs-news-feeder project ensures code quality, correctness of utility functions, and the validity of the generated RSS feed. The approach combines automated unit tests for core logic, linting for code style consistency, and external validation for the final RSS output.
The primary testing framework is the native Node.js test runner, configured to run tests, generate coverage reports, and watch for file changes. Additionally, the project includes a manual testing interface for adding posts and a validation script that uses the W3C Feed Validation service to ensure the generated feed.xml is compliant.
Sources: package.json:18-20, utils/tests/utils.test.js, scripts/validate.js, README.md:46-52
Testing Framework and Scripts
The project utilizes Node.js's built-in test runner for executing tests. The testing scripts are defined in package.json and provide commands for running tests, watching for changes, and generating coverage reports. Code quality and style are enforced using standard.
Sources: package.json:18-20, 21-22
NPM Scripts
The following table outlines the available scripts for testing and quality assurance.
| Script | Description |
|---|---|
npm run lint | Runs the standard linter to check for code style issues. |
npm run lint:fix | Runs the standard linter and automatically fixes any fixable issues. |
npm run test | Executes the test suite using the native Node.js test runner. The TZ environment variable is set to 'Europe/Amsterdam'. |
npm run test:watch | Runs the tests in watch mode, re-running them whenever a file changes. |
npm run test:coverage | Runs the tests and generates a lcov.info coverage report. |
npm run rss:validate | Validates the generated feed.xml against the W3C Feed Validation service. |
Sources: package.json:18-22, README.md:46-63
An example of the test script configuration in package.json:
"scripts": {
...
"lint": "standard",
"lint:fix": "standard --fix",
"test": "env TZ='Europe/Amsterdam' node --test",
"test:coverage": "env TZ='Europe/Amsterdam' node --test --test-reporter=lcov --test-reporter-destination=lcov.info",
"test:watch": "env TZ='Europe/Amsterdam' node --test --watch"
...
}
Sources: package.json:18-22
Unit Testing
Unit tests are focused on the utility functions located in utils/index.js. The tests are written in utils/__tests__/utils.test.js and use the native Node.js node:test and node:assert/strict modules.
Sources: utils/tests/utils.test.js:1-10
Test Structure
Tests are organized into describe blocks, which group tests for a specific module or function. Each individual test case is defined within an it block, which contains assertions to verify the function's behavior.
This diagram shows the relationship between the test file and the utility functions it covers.
Sources: utils/tests/utils.test.js, utils/index.js
Tested Utility Functions
The test suite provides comprehensive coverage for various string and date manipulation functions critical for generating clean and valid XML/HTML content.
| Function | Description |
|---|---|
buildRFC822Date | Converts a date string into the RFC 822 format required for RSS feeds. |
escapeXmlCharacters | Escapes special XML characters like &, <, >, ", and '. |
stripHtmlTags | Removes all HTML tags from a string. |
escapeHtmlTags | Escapes HTML tag brackets (< and >) to display them as text. |
normalizeLineEndings | Converts Windows-style line endings (\r\n) to Unix-style (\n). |
normalizeWhitespace | Collapses multiple whitespace characters into a single space. |
removeControlCharacters | Removes most ASCII control characters, preserving tab, newline, and carriage return. |
Sources: utils/tests/utils.test.js:5-10, utils/index.js
An example test case for the escapeXmlCharacters function:
// from utils/__tests__/utils.test.js
describe('escapeXmlCharacters', () => {
it('should escape XML special characters', () => {
strictEqual(escapeXmlCharacters('Hello & World'), 'Hello & World');
strictEqual(escapeXmlCharacters('Price < 100'), 'Price < 100');
strictEqual(escapeXmlCharacters('Value > 50'), 'Value > 50');
strictEqual(escapeXmlCharacters('Say "Hello"'), 'Say "Hello"');
strictEqual(escapeXmlCharacters("It's working"), 'It's working');
});
it('should handle non-string inputs', () => {
strictEqual(escapeXmlCharacters(null), null);
strictEqual(escapeXmlCharacters(undefined), undefined);
strictEqual(escapeXmlCharacters(123), 123);
});
});
Sources: utils/tests/utils.test.js:18-37
RSS Feed Validation
The project includes a script to validate the generated feed.xml file. This is a crucial step to ensure the feed is consumable by RSS readers and other services.
Sources: scripts/validate.js, package.json:14
Validation Process
The npm run rss:validate command executes the scripts/validate.js script. This script reads the local feed.xml, sends its content in a POST request to the W3C Feed Validation service (https://validator.w3.org/feed/check.cgi), and parses the HTML response to determine if the feed is valid.
The following sequence diagram illustrates the RSS validation flow.
Sources: scripts/validate.js:4-26
If the response title from the validator is "Sorry", it indicates an invalid feed, and the script logs an error. Otherwise, it confirms that the feed is valid.
Sources: scripts/validate.js:21-25
Manual Post Management
The application includes a simple Express server and a web interface for manually adding and viewing posts. This serves as a development and manual testing tool to manage entries in manual-posts.json.
Sources: server.js, add-post.html
API Endpoints
The server exposes two main endpoints for managing posts:
| Method | Endpoint | Description |
|---|---|---|
GET | /api/posts | Retrieves all posts from manual-posts.json. |
POST | /api/posts | Adds a new post to manual-posts.json. It automatically generates an id and a published_at timestamp. |
Sources: server.js:14-41
Manual Testing Flow
The add-post.html page provides a form to submit new posts and a list to view existing ones. When the form is submitted, a POST request is sent to the /api/posts endpoint. The page then refreshes the list by making a GET request.
This sequence diagram shows the flow of adding a new manual post.
Sources: add-post.html:47-73, server.js:28-41