jestjs / jest

Delightful JavaScript Testing.
https://jestjs.io
MIT License
44k stars 6.42k forks source link

[Feature]: Programmatic api to resolve the entire config and run jest #14034

Open nicojs opened 1 year ago

nicojs commented 1 year ago

πŸš€ Feature Proposal

Hi πŸ™‹β€β™‚οΈ It's me again πŸ˜….

We currently use this code to resolve the jest config programmatically:

const requireFromJest = createRequire(require.resolve('jest', { paths: [resolveFromDirectory] }));
const requireFromJestCli = createRequire(requireFromJest.resolve('jest-cli'));
const jestConfig = requireFromJestCli('jest-config');
const { config, configPath } = jestConfig.readInitialOptions();

However, this doesn't seem to resolve presets. I.e. this:

// jest.config.js
module.exports = { preset: 'jest-preset-angular' };

Results in { preset: 'jest-preset-angular' }

I would love a way to resolve the entire config inc presets and use that config to run jest.

Motivation

In StrykerJS, we're running jest programmatically in the @stryker-mutator/jest-runner plugin. We need to wrap around the user's configured test environment because we need access to the global variables to report mutation coverage; we're using the workaround specified here: https://github.com/facebook/jest/issues/7421#issuecomment-442451426

To do that, we want to know which test environment the user configured. That way, we can override that test environment by a class that extends the user's test environment (a mixin class):

function mixinJestEnvironment(JestEnvironmentClass) {
   class StrykerJestEnvironment extends JestEnvironmentClass {
      constructor(config, context) {
        super(config, context);
        this.global.__stryker__ = globalThis.__stryker__; // coverage is reported on __stryker__
      }
      // ...
  }
  return StrykerJestEnvironment;
}

When the testEnvironment is empty, we assume the default ("node"), which is incorrect when the preset would override to, say, "jsdom".

See also: https://github.com/stryker-mutator/stryker-js/issues/4068

Example

Ideally, we would like to read the config for a project and use that in the runCLI API (or similar API).

const requireFromJest = createRequire(require.resolve('jest', { paths: [process.cwd()] }));
const requireFromJestCli = createRequire(requireFromJest.resolve('jest-cli'));
const jest = requireFromJestCli('jest');
const jestConfig = requireFromJestCli('jest-config');
const { globalConfig, projectConfig} = jestConfig.readConfig(argv);

// Override the jest env
globalThis.originalJestEnv = projectConfig.testEnvironment ?? globalConfig.testEnvironment ?? 'node';
projectConfig.testEnvironment  = 'stryker-jest-env';

const { results } = await jest.run(globalConfig, projectConfig);

Pitch

A proper programmatic API would help the mission for Jest as a Platform.

nicojs commented 1 year ago

It might be pretty straightforward to export and document _run10000 https://github.com/facebook/jest/blob/b38d7d345a81d97d1dc3b68b8458b1837fbf19be/packages/jest-core/src/cli/index.ts#L170

SimenB commented 1 year ago

I would guess that using readConfig (or readConfigs) instead of readInitialOptions would work? Untested, tho

nicojs commented 1 year ago

Yes, that would work. The problem is that there is currently no api (private or public) to run jest with that config.

SimenB commented 1 year ago

Aha. Happy to expose that πŸ™‚

nicojs commented 1 year ago

F.y.i. I was wondering why it was called _run10000. But I found it here 😁: https://github.com/facebook/jest/pull/10000/files

nicojs commented 1 year ago

@SimenB I've started some work and presented it in a draft PR: #14062

Please confirm I'm on the right track. I'll add more tests and document the whole thing in /docs when you confirm ☺

github-actions[bot] commented 1 year ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days.

nicojs commented 1 year ago

It's not stale! It has an active PR πŸ˜‡

github-actions[bot] commented 1 year ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days.

nicojs commented 1 year ago

Please keep it open

github-actions[bot] commented 1 year ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days.

nicojs commented 1 year ago

Yeah, I'll get around to it eventually. Plz keep open

github-actions[bot] commented 1 year ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days.

deribaucourt commented 10 months ago

Hi, I'm really interested by this feature! My use case is to run integration tests on a VSCode Extension. Basically, I want to run jest tests inside the VSCode runtime. This is well documented in VSCode, and I'm currently able to do a jest.run/jest.runCli inside the VSCode environment. However, these functions fork into another process which loses all that context.

Would the current PR allow to run Jest without forking?

Thanks for your dedication!