avajs / ava

Node.js test runner that lets you develop with confidence 🚀
MIT License
20.74k stars 1.41k forks source link

TypeError: require(...).getRunner is not a function #2847

Closed vjpr closed 3 years ago

vjpr commented 3 years ago

Please provide details about:

v4

Run a test


  Uncaught exception in src/index.test.ava.ts

  TypeError: require(...).getRunner is not a function

    stack: 'TypeError: require(...).getRunner is not a function\n' +
      '    at Object.<anonymous> (/xxx/node_modules/.pnpm/ava@4.0.0-alpha.2_d9427be2a42752c1fe4520f1b97b7be4/node_modules/ava/lib/worker/main.js:2:34)\n' +
      '    at Module._compile (node:internal/modules/cjs/loader:1101:14)\n' +
      '    at Module._extensions..js (node:internal/modules/cjs/loader:1153:10)\n' +
      '    at Object.require.extensions.<computed> [as .js] (/Users/Vaughan/nvm/versions/node/v16.7.0/pnpm-global/5/node_modules/.pnpm/ava@4.0.0-alpha.2/node_modules/ava/lib/worker/dependency-tracker.js:43:4)\n' +
      '    at Module.load (node:internal/modules/cjs/loader:981:32)\n' +
      '    at Function.Module._load (node:internal/modules/cjs/loader:822:12)\n' +
      '    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:196:29)\n' +
      '    at ModuleJob.run (node:internal/modules/esm/module_job:183:25)\n' +
      '    at processTicksAndRejections (node:internal/process/task_queues:96:5)\n' +
      '    at Loader.import (node:internal/modules/esm/loader:178:24)',

  Uncaught exception in src/index.test.ava.ts

  TypeError: Cannot read property 'chalkOptions' of undefined

    stack: "TypeError: Cannot read property 'chalkOptions' of undefined\n" +
      '    at run (/Users/Vaughan/dev-mono/thirtyfive/node_modules/.pnpm/ava@4.0.0-alpha.2_d9427be2a42752c1fe4520f1b97b7be4/node_modules/ava/lib/worker/base.js:26:34)\n' +
      '    at Object.<anonymous> (/Users/Vaughan/dev-mono/thirtyfive/node_modules/.pnpm/ava@4.0.0-alpha.2_d9427be2a42752c1fe4520f1b97b7be4/node_modules/ava/lib/worker/base.js:255:2)\n' +
      '    at Module._compile (node:internal/modules/cjs/loader:1101:14)\n' +
      '    at Module._extensions..js (node:internal/modules/cjs/loader:1153:10)\n' +
      '    at Object.require.extensions.<computed> [as .js] (/Users/Vaughan/nvm/versions/node/v16.7.0/pnpm-global/5/node_modules/.pnpm/ava@4.0.0-alpha.2/node_modules/ava/lib/worker/dependency-tracker.js:43:4)\n' +
      '    at Module.load (node:internal/modules/cjs/loader:981:32)\n' +
      '    at Function.Module._load (node:internal/modules/cjs/loader:822:12)\n' +
      '    at Module.require (node:internal/modules/cjs/loader:1005:19)\n' +
      '    at require (node:internal/modules/cjs/helpers:94:18)\n' +
      '    at Object.<anonymous> (/Users/Vaughan/dev-mono/thirtyfive/node_modules/.pnpm/ava@4.0.0-alpha.2_d9427be2a42752c1fe4520f1b97b7be4/node_modules/ava/lib/worker/main.js:2:16)',

Works.

Config

import {join} from 'path'
import fs from 'fs'
import {resolve} from 'import-meta-resolve'

export default (overrides = {}) =>
  async ({projectDir}) => {
    console.log('Ava using project dir:', projectDir)

    const loaderStr = await resolve(
      '@live/esm-loader/index.js',
      import.meta.url,
    )

    const config = {
      verbose: true,
      extensions: {
        ts: 'module',
      },
      nonSemVerExperiments: {
        //nextGenConfig: true,
        //configurableModuleFormat: true,
      },
      nodeArguments: [
        '--no-warnings',
        `--experimental-loader=${loaderStr}`,
        '--conditions=transpile',
        '--experimental-specifier-resolution=node',
        '--experimental-import-meta-resolve',
      ],
      files: [
        '**/*.test.ava.ts',
        '!**/node_modules/**', // I think this is ignored by default. Maybe not needed here.
        '!.dev/**', // This was needed otherwise we get some `ENAMETOOLONG` error. Probably from circular symlinks or something.
      ],
      ignoredByWatcher: ['.dev'],
      ...overrides,
    }

    return config
  }
vjpr commented 3 years ago

So '--experimental-specifier-resolution=node' was causing this error.

Although its also caused by '--loader=ts-node/esm'.


I don't understand how this is suppose to work. When require(base) is called, the async run is kicked off which sets the getRunner export. So getRunner will not be set by the time the module is returned.

main.js

const runner = require('./base').getRunner();
module.exports = runner.chain;

base.js

async run = () => {
...
    let accessedRunner = false;
    exports.getRunner = () => {
        accessedRunner = true;
        return runner;
    };
...
}

if (isRunningInThread) {
    const {workerData} = require('worker_threads');
    const {options} = workerData;
    delete workerData.options; // Don't allow user code access.
    run(options).catch(onError);
} else if (isRunningInChildProcess) {
    channel.send({type: 'ready-for-options'});
    channel.options.then(run).catch(onError); // eslint-disable-line promise/prefer-await-to-then
}

Also, I dont get the chalkOptions error when using ava --no-worker-threads.

vjpr commented 3 years ago

I think I found my issue. I am using pnpm and two different versions of ava are being used - a global one and a local one. I've seen this elsewhere with workers. It depends on how the path to the worker script is being resolved.

base.js

Trace: { getRunner: [Function (anonymous)] }
    at run (/Users/Vaughan/nvm/versions/node/v16.7.0/pnpm-global/5/node_modules/.pnpm/ava@4.0.0-alpha.2/node_modules/ava/lib/worker/base.js:142:10)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)

main.js

Trace:
    at Object.<anonymous> (/Users/Vaughan/dev-mono/thirtyfive/node_modules/.pnpm/ava@4.0.0-alpha.2_d9427be2a42752c1fe4520f1b97b7be4/node_modules/ava/lib/worker/main.js:3:9)
    at Module._compile (node:internal/modules/cjs/loader:1101:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Object.require.extensions.<computed> [as .js] (/Users/Vaughan/nvm/versions/node/v16.7.0/pnpm-global/5/node_modules/.pnpm/ava@4.0.0-alpha.2/node_modules/ava/lib/worker/dependency-tracker.js:43:4)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:196:29)
    at ModuleJob.run (node:internal/modules/esm/module_job:183:25)
    at Loader.import (node:internal/modules/esm/loader:178:24)
    at importModuleDynamicallyWrapper (node:internal/vm/module:437:15)

So when ava is invoked globally, it invokes its workers locally when using pnpm...I think.

novemberborn commented 3 years ago

AVA 4 no longer wants to be installed globally, see the discussion in https://github.com/avajs/ava/commit/1ee1e82678a9a2024d2635a9adeb8f14d98669f8.

pnpm exec ava should work.