Heuristic:DevExpress Testcafe Docker Chrome Tab Retry
| Knowledge Sources | |
|---|---|
| Domains | Containerization, Browser_Automation |
| Last Updated | 2026-02-12 03:30 GMT |
Overview
Chrome in Docker opens a non-working initial tab; TestCafe retries tab listing for up to 10 seconds with 500ms intervals and creates a new tab for the test page.
Description
When Chrome starts inside a Docker container, it opens a default tab that is not usable for testing. TestCafe's `startOnDocker` function handles this by: (1) launching Chrome, (2) repeatedly polling the CDP `List` endpoint at 500ms intervals for up to 10 seconds until tabs are available, and (3) creating a new tab via CDP `New` to load the test page URL. The tab listing retry loop accounts for Chrome's slower startup time in containerized environments where resources may be limited. On Linux (outside Docker), Chrome may also require two SIGTERM signals to fully close.
Usage
This heuristic is important when running TestCafe in Docker containers or debugging Docker-specific Chrome startup issues. If Chrome fails to start within 10 seconds in your container, the test will fail with a browser connection error. Consider increasing system resources or ensuring Chrome is not competing with other processes for CPU.
The Insight (Rule of Thumb)
- Action: No configuration needed; Docker handling is automatic when `is-docker` or `is-podman` detects a container. Ensure sufficient resources in Docker container.
- Value: Tab listing timeout: 10 seconds. Retry interval: 500ms. Max retries: ~20.
- Trade-off: The 10-second timeout adds to Docker startup latency but handles slow Chrome initialization gracefully. Chrome in containers is generally slower to start than on bare metal.
Reasoning
Container environments have less direct hardware access and may have limited shared memory (`/dev/shm`). Chrome's `--disable-dev-shm-usage` flag (automatically added in containers) forces Chrome to use `/tmp` instead, which is slower. The default tab that Chrome opens is a chrome-internal page that cannot be navigated to test URLs. The retry loop ensures TestCafe waits for Chrome to be fully operational before attempting to create test tabs.
Code Evidence
From `src/browser/provider/built-in/dedicated/chrome/local-chrome.js:11-13`:
const LIST_TABS_TIMEOUT = 10000;
const LIST_TABS_DELAY = 500;
Docker tab creation flow from `src/browser/provider/built-in/dedicated/chrome/local-chrome.js:30-43`:
export async function startOnDocker (pageUrl, { browserName, config, cdpPort, tempProfileDir, isContainerized }) {
await start('', { browserName, config, cdpPort, tempProfileDir, isContainerized });
let { tabs, error } = await tryListTabs(cdpPort);
const timer = new Timer(LIST_TABS_TIMEOUT);
//NOTE: We should repeat getting 'List' after a while because we can get an error if the browser isn't ready.
while ((error || !tabs.length) && !timer.expired) {
await delay(LIST_TABS_DELAY);
({ tabs, error } = await tryListTabs(cdpPort));
}
Chrome on Linux signal behavior from `src/browser/provider/built-in/dedicated/chrome/local-chrome.js:56`:
// NOTE: Chrome on Linux closes only after the second SIGTERM signal