Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: getState from jest-circus gets state from parellel environment #15018

Open
timcharper opened this issue Apr 7, 2024 · 2 comments
Open

Comments

@timcharper
Copy link

timcharper commented Apr 7, 2024

Version

29.7.0

Steps to reproduce

  1. Clone https://github.com/timcharper/jest-circus-issue
  2. Install dependencies
  3. Run jest src/__tests__/add.test.js

Expected behavior

I expect getState to return the state that I'm in the "lol" describe block, not the root block

Actual behavior

getState returns wrong state object, because jest-circus gets loaded twice, and the state symbol for JEST_STATE_SYMBOL is instantiated with Symbol("JEST_STATE_SYMBOL") instead of Symbol.for("JEST_STATE_SYMBOL")`.

Additional context

Here's the log output from when I run the test in my repro project:

 $ jest src/__tests__/add.test.js
  console.log
    {
      type: 'describeBlock',
      children: [],
      hooks: [],
      mode: undefined,
      name: 'ROOT_DESCRIBE_BLOCK',
      parent: undefined,
      tests: []
    }

      at log (src/__tests__/add.test.js:8:11)

  console.log
    [ Symbol(JEST_STATE_SYMBOL), Symbol(JEST_STATE_SYMBOL) ]

      at log (src/__tests__/add.test.js:11:11)

  console.log
    {
      stateFromGlobal: [
        {
          type: 'describeBlock',
          children: [],
          hooks: [],
          mode: undefined,
          name: 'lol',
          parent: [Object],
          tests: []
        },
        {
          type: 'describeBlock',
          children: [],
          hooks: [],
          mode: undefined,
          name: 'ROOT_DESCRIBE_BLOCK',
          parent: undefined,
          tests: []
        }
      ]
    }

      at log (src/__tests__/add.test.js:12:11)

 PASS  src/__tests__/add.test.js
  lol
    ✓ adds 1 + 2 to equal 3 (1 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.28 s, estimated 1 s
Ran all test suites matching /src\/__tests__\/add.test.js/i.

Environment

System:
    OS: Linux 6.5 Ubuntu 23.10 23.10 (Mantic Minotaur)
    CPU: (16) x64 Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz
  Binaries:
    Node: 20.5.1 - ~/.asdf/installs/nodejs/20.5.1/bin/node
    Yarn: 1.22.19 - ~/.asdf/installs/nodejs/20.5.1/bin/yarn
    npm: 9.8.0 - ~/.asdf/plugins/nodejs/shims/npm
  npmPackages:
    jest: ^29.7.0 => 29.7.0
@timcharper
Copy link
Author

this is a terrible workaround that works:

import { State, getState } from "jest-circus";

type GlobalKey = keyof typeof global;

let jestStateSymbol: GlobalKey | undefined;

function findStateSymbols(): GlobalKey[] {
  return Reflect.ownKeys(global).filter(
    (key) => key.toString() == "Symbol(JEST_STATE_SYMBOL)"
  ) as GlobalKey[];
}

/** jest-circus state handling is a clown town
 * See https://github.com/jestjs/jest/issues/15018 for more information
 *
 * This method is a work-around which grabs the correct state object
 */
export function getJestState(): State {
  // If we have successfully found state before, keep using the symbol.
  if (jestStateSymbol) return global[jestStateSymbol];

  /* there can be 0-2 state symbols:
     0: state not yet initialized
     1: only `describe` invocations has led to updated / accessed state, OR, getState was called by another module
     2: both `describe` and another module has accessed state via getState. */

  for (const symbol of findStateSymbols()) {
    const state: State | undefined = global[symbol];
    // undefined? keep looking
    if (!state) continue;
    // root block? likely the wrong one. Keep looking
    if (!state.currentDescribeBlock.parent) continue;
    // we found it? remember it going forward
    jestStateSymbol = symbol;
    return state;
  }
  // didn't find anything? Just return the root state (which getState always returns, because of the bug).
  return getState();
}

Copy link

github-actions bot commented May 8, 2024

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.

@github-actions github-actions bot added the Stale label May 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant