dockere2e-testingtestcafe

How to use TestCafe inside docker container?


I am trying to run TestCafe tests inside a docker container.

Tests are working as excepted with runner or cli locally without container. When I try to run inside docker container, this error appears:

ERROR Cannot find the browser. "/bin/sh" is neither a known browser alias, nor a path to an executable file.

I am using testcafe/testcafe image as a starter in container and installing other packages with npm. As far as I read from docs, testcafe image comes with chrome. Dockerfile:

FROM testcafe/testcafe
USER root

WORKDIR /app
COPY package*.json .
RUN npm install --force --legacy-peer-deps --progress=false

CMD npm run testrunner # this is a command that i define in package.json

package.json

{
  ...
  "main": "index.js",
  "scripts": {
    "cafe:prod:h:3": "npx testcafe 'chrome:headless' --concurrency 3 src/tests/masterdata",
    "testrunner": "node runner.js"
  },
  ...
  "dependencies": {
    "@aws-sdk/client-ssm": "^3.535.0",
    "aws-sdk": "^2.1582.0",
    "dotenv": "^16.4.5",
    "downloads-folder": "^3.0.3",
    "testcafe": "^3.5.0",
    "testcafe-browser-tools": "^2.0.26"
  }
}

runner.js

const createTestCafe = require('testcafe');

(async function () {
  const testcafe = await createTestCafe();
  try {
    const runner = testcafe.createRunner();
    const failed = await runner.src(['src/tests/masterdata']).browsers('chrome:headless').concurrency(3).run();

    console.log('Tests failed: ' + failed);
  } finally {
    await testcafe.close();
  }
})();

I am not referring /bin/sh anywhere in my code. Why testcafe try to use docker from this path? How can I run runner.js inside of the container?


Solution

  • The error message and documentation suggest that the base image you're using declares the testcafe tool as the image's ENTRYPOINT, which means the CMD isn't actually a command but only arguments to testcafe. If CMD is a string, then Docker automatically wraps it in /bin/sh -c '...', which results in the specific error you're seeing.

    If you wanted to run the image this way, you'd need to copy the testcafe arguments out of package.json into the Dockerfile. This would be the CMD, even though it isn't really "a command", and it must use the JSON-array syntax that's not interpreted with a shell. Don't forget to also copy the tests into the image too.

    COPY src/tests/ src/tests/
    CMD ["chrome:headless", "--concurrency", "3", "src/tests/masterdata"]
    

    If you want to keep the tools that the base image bundles but run your own command instead, you need to override the base image's ENTRYPOINT. One choice can be to set it to an empty JSON array, at which point CMD reverts to being a normal command.

    COPY ./ ./
    ENTRYPOINT []
    CMD npm run testrunner