Testing Strategy
Relevant source files
The following files were used as context for generating this wiki page:The testing strategy for Rendertron ensures the reliability and correctness of its core functionalities, including page rendering, screenshot generation, middleware logic, and caching. The project employs a combination of integration and unit tests using the Ava test framework, Supertest for HTTP assertions, and dedicated test servers to simulate real-world scenarios.
Tests are organized by feature, with separate test suites for the main application, the Express middleware, and the Datastore caching layer. This modular approach allows for focused testing of each component, verifying everything from basic rendering and script execution to complex interactions like bot detection and cache invalidation.
Testing Framework and Tools
The project leverages several key libraries and tools to build and execute its test suites. The primary test runner is Ava, a concurrent test runner for Node.js. HTTP requests and assertions are handled by Supertest.
Sources: package.json:14-21, package.json:52-56
| Tool | Version | Description |
|---|---|---|
ava | 1.0.0-beta.6 | The core test runner for executing test files. |
supertest | ^3.0.0 | An HTTP assertion library for testing Node.js HTTP servers. |
koa | ^2.5.2 | Used to create test servers for the main application and caching tests. |
express | ^4.16.3 | Used to create a test server for the middleware tests. |
puppeteer | ^1.7.0 | The core dependency for headless Chrome automation, which Rendertron is built upon. |
tslint | ^5.11.0 | Used for linting the TypeScript codebase. |
The test scripts defined in package.json orchestrate the execution of these tests, including building the project and setting up necessary emulators.
"scripts": {
"test": "(cd test-resources && npm install) && npm run build && ava build/test/app-test.js --timeout 5s",
"start-emulator": "(gcloud beta emulators datastore start --no-store-on-disk --project emulator-project &) 2>&1 | grep -m1 'now running'",
"test-cache": "npm run start-emulator && $(gcloud beta emulators datastore env-init) && export GCLOUD_PROJECT='emulator-project' && ava build/test/datastore-cache-test.js"
}
Sources: package.json:19-21
Core Application Testing
The core application tests, located in src/test/app-test.ts, focus on the main Rendertron service. These are integration tests that spin up a full Rendertron server instance and a separate Koa server to serve static test files from the test-resources directory.
Sources: src/test/app-test.ts
Test Setup
Before any tests are run, two servers are initialized:
- A
Rendertronserver instance, which is the system under test. - A
Koaserver that useskoa-staticto serve HTML files from thetest-resourcesdirectory. This acts as the target website to be rendered.
This diagram illustrates the test setup flow.
Sources: src/test/app-test.ts:25-32
Test Scenarios
A variety of scenarios are tested to ensure the rendering and screenshot endpoints behave as expected.
| Feature | Endpoint | Description |
|---|---|---|
| Health Check | GET /_ah/health | Verifies that the service is running and returns a 200 OK status. |
| Basic Rendering | GET /render/<url> | Renders a simple page and checks for the presence of dynamically generated content. |
| Shadow DOM | GET /render/<url>?wc-inject-shadydom=true | Tests rendering of pages with Shadow DOM, ensuring polyfills are correctly applied. |
| Script Stripping | GET /render/<url> | Ensures that <script> and <link rel="import"> tags are removed from the final serialized HTML, but preserves JSON-LD script tags. |
| Status Code Forwarding | GET /render/<url> | Confirms that the HTTP status code from the target URL (e.g., 404) is forwarded by the Rendertron service. |
| Meta Tag Status Code | GET /render/<url> | Tests the ability to override the response status code using a <meta name="render:status_code" content="400"> tag. |
| Screenshot | POST /screenshot/<url> | Verifies that the screenshot endpoint returns a JPEG image and accepts options in the POST body. |
| URL Validation | GET /render/<url> | Checks that invalid, unknown, or forbidden (e.g., file:///) URLs are rejected with appropriate error codes (403 or 400). |
Sources: src/test/app-test.ts:34-184, test-resources/http-meta-status-code.html:15
Middleware Testing
The Express middleware is tested in middleware/src/test/middleware-test.ts. These tests verify the logic that determines whether to proxy a request to the Rendertron service or to pass it through to the next handler.
Test Setup
The middleware tests create two Express servers:
- App Server: An Express app that uses the Rendertron middleware. If the middleware calls
next(), this server responds with "fallthrough". - Proxy Server: A mock Rendertron server that responds with "proxy <decoded_url>", allowing tests to verify that a request was correctly proxied.
Sources: middleware/src/test/middleware-test.ts:32-51
This sequence diagram shows the interaction between a client, the app server with middleware, and the mock proxy during a test.
Test Scenarios
Key middleware behaviors are validated:
- Proxying Bots: Requests with bot-like
User-Agentheaders are proxied. - Ignoring Humans: Requests with normal browser
User-Agentheaders fall through. - URL Exclusion: Requests for static file extensions (e.g.,
.png) are ignored by default. - Custom Patterns: The
userAgentPatternandexcludeUrlPatternoptions are respected. - Error Forwarding: HTTP error statuses from the proxy are forwarded to the client.
- Timeout: If the proxy request times out, the middleware falls through to the next handler.
Sources: middleware/src/test/middleware-test.ts:76-173
Datastore Cache Testing
The optional Datastore caching layer is tested in src/test/datastore-cache-test.ts. These tests require a Google Cloud Datastore emulator, which is started via the npm run start-emulator script.
Test Logic
The tests verify the complete caching lifecycle:
- A first request is made to an endpoint. The handler is executed, and the response is stored in the Datastore cache.
- A second request is made to the same endpoint. The response is served directly from the cache, and the original handler is not called again.
- The
x-rendertron-cachedheader is present on cached responses. - Response headers and content encoding (like gzip) are correctly cached and restored.
- Responses with non-200 status codes are not cached.
Sources: src/test/datastore-cache-test.ts:47-142, src/datastore-cache.ts:88-118
This sequence diagram illustrates the caching test flow.
Test Resources
The test-resources/ directory contains a collection of simple HTML files, each designed to trigger and validate a specific behavior of the renderer. A Koa static server serves these files during the core application tests.
| File | Purpose |
|---|---|
basic-script.html | Tests if a simple inline script that modifies the DOM is executed correctly. |
shadow-dom-polyfill-loader.html | Validates rendering of Shadow DOM with polyfills. |
include-script.html | Checks that script tags are stripped from the output. |
include-json-ld.html | Ensures that application/ld+json script tags are preserved. |
http-meta-status-code.html | Tests if a <meta> tag can override the HTTP status code. |
explicit-render-event.html | Contains a script that fires a renderComplete event to signal rendering is done. |
Sources: src/test/app-test.ts:26-27, test-resources/basic-script.html, test-resources/http-meta-status-code.html, test-resources/explicit-render-event.html
Summary
The testing strategy for Rendertron is comprehensive, covering all critical aspects of the service. By using a combination of a real Rendertron instance, mock servers, and a dedicated set of test resources, the tests provide high confidence in the correctness of rendering, middleware logic, and caching performance. The clear separation of tests for each major component allows for maintainable and targeted validation of functionality.
Sources: src/test/app-test.ts, middleware/src/test/middleware-test.ts, src/test/datastore-cache-test.ts