Cannot find module in CodeceptJS Docker container

I have a small Codecept project that runs fine in my local development machine. However, on our Jenkins pipeline server, I am trying to get it to run in a Jenkins container agent, using a slim Dockerfile based on the codeceptjs/codeceptjs Docker image.

When I run it I get an error that it can’t find some extra Node modules I’m including ( dotenv, jsonwebtoken ).

What I have tried

So far I’ve tried:

  • In the Dockerfile, running npm install --global dotenv jsonwebtoken, both as the main user and as the pptruser from the Codecept Dockerfile.
  • In the Dockerfile, running npm install locally in the /codecept directory.
  • Running npm install from my test directory, which has a package.json. When I do that, it creates a node_modules folder in my test folder, and then the problem I get is it can’t find the module @codeceptjs/configure which I know installs in the main /codecept folder in the image.

Code snippets

package.json

{
    "name": "codeceptjs-tests",
    "version": "0.1.0",
    "private": true,
    "scripts": {
        "codeceptjs": "codeceptjs run --steps",
        "codeceptjs:headless": "HEADLESS=true codeceptjs run --steps",
        "codeceptjs:ui": "codecept-ui --app",
        "codeceptjs:demo": "codeceptjs run --steps -c node_modules/@codeceptjs/examples/codecept.webdriver.conf.js",
        "codeceptjs:demo:headless": "HEADLESS=true codeceptjs run --steps -c node_modules/@codeceptjs/examples/codecept.webdriver.conf.js",
        "codeceptjs:demo:ui": "codecept-ui --app  -c node_modules/@codeceptjs/examples/codecept.webdriver.conf.js"
    },
    "devDependencies": {
        "@codeceptjs/configure": "^0.6.2",
        "@codeceptjs/examples": "^1.2.1",
        "@codeceptjs/ui": "^0.4.3",
        "codeceptjs": "^3.0.5",
        "playwright": "^1.9.1"
    },
    "dependencies": {
        "dotenv": "^8.2.0",
        "jsonwebtoken": "^8.5.1",
        "mocha": "^2.2.5",
        "mocha-junit-reporter": "^1.23.1"
    }
}

Dockerfile

This is the Dockerfile used as the Jenkins container agent.

FROM codeceptjs/codeceptjs

RUN apt-get install mmv
RUN npm install --global dotenv@8.2.0 jsonwebtoken@8.5.1

Jenkinsfile

The piece of the Jenkinsfile that runs CodeceptJS.

        stage('UI tests') {
            agent {
                dockerfile {
                    dir 'tests/ui'
                    args '--network host --entrypoint=\'\''
                }
            }
            environment {
                HOME = '.'
                HEADLESS = 1
            }
            steps {
                milestone 40
                sh "chmod +x ${WORKSPACE}/tests/ui/run-pipeline.sh"
                sh "${WORKSPACE}/tests/ui/run-pipeline.sh"
            }

codecept.confi.js

require('dotenv').config()

const { setHeadlessWhen } = require('@codeceptjs/configure');

// turn on headless mode when running with HEADLESS=true environment variable
// export HEADLESS=true && npx codeceptjs run
setHeadlessWhen(process.env.HEADLESS);

var anyProfile = !(process.env.profile == undefined || process.env.profile == 'undefined');
var browser = anyProfile ? process.env.profile : 'chromium';

exports.config = {
    tests: './*_test.js',
    output: './output',
    helpers: {
        Playwright: {
            url: 'http://localhost:720',
            show: process.env.HEADLESS != 1,
            browser: browser, // chromium | firefox | webkit
            waitForNavigation: "networkidle" // Webkit froze on page redirect if this was left at default of 'load'
        }
    },
    include: {
        I: './steps_file.js'
    },
    bootstrap: null,
    mocha: {
        reporterOptions: {
            mochaFile: "output/result.xml",
            useFullSuiteTitle: true,
            rootSuiteTitle: `UI Tests (${browser})`,
            jenkinsMode: true
        },
    },
    name: 'ui',
    plugins: {
        pauseOnFail: {},
        retryFailedStep: {
            enabled: true
        },
        tryTo: {
            enabled: true
        },
        screenshotOnFail: {
            enabled: true
        }
    }
}

run-pipeline.sh

This is the bit that runs inside the container and fails with "Cannot find module dotenv"

if ! xvfb-run -a --server-args="-screen 0 1024x768x24" "codeceptjs" run --steps --profile chromium --reporter mocha-junit-reporter ; then
    success=false
fi
mmv 'output/*.*' 'output-archive/chrome.#1.#2'