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

jest-each tests fail when using parameters set in beforeAll #7100

Closed
monicajianu opened this issue Oct 4, 2018 · 9 comments
Closed

jest-each tests fail when using parameters set in beforeAll #7100

monicajianu opened this issue Oct 4, 2018 · 9 comments

Comments

@monicajianu
Copy link

🐛 Bug Report

You cannot pass a variable set in the beforeAll block as a parameter to a parameterized test, as .each is run before beforeAll.

To Reproduce

let values
beforeAll(() => {
  values = ['hello', 'world']
})

describe('test setting variable in before all', () => {
  test('non-parameterized', () => {
    expect(values).toHaveLength(2) // passes
  })

  test.each(values)('parameterized', (value) => {
    expect(value).toBeDefined() // fails - values is undefined
  })

  let otherValues = [1, 2, 3]
  test.each(otherValues)('parameterized with variable set right before test', (value) => {
    expect(value).toBeDefined() // passes
  })
})

Expected behavior

The beforeAll block should run before a parameterized test, in order to match the behaviour in non-parameterized tests.

Link to repl or repo (highly encouraged)

N/A see block of code above

Run npx envinfo --preset jest

 System:
    OS: macOS High Sierra 10.13.6
    CPU: x64 Intel(R) Core(TM) i7-7820HQ CPU @ 2.90GHz
  Binaries:
    Node: 8.9.4 - ~/.nvm/versions/node/v8.9.4/bin/node
    npm: 6.1.0 - ~/.nvm/versions/node/v8.9.4/bin/npm
  npmPackages:
    jest: ^23.4.0 => 23.4.0 
@rickhanlonii
Copy link
Member

@mattphillips what do you think about this?

@SimenB
Copy link
Member

SimenB commented Oct 11, 2018

All tests tests and hooks are collected before we start executing any of them, so you cannot use dynamic data from a hook to define its or tests (which .each is sugar for)

@SimenB SimenB closed this as completed Oct 11, 2018
@mattphillips
Copy link
Contributor

Related issue: #6888

As @SimenB said tests need to be defined synchronously. Perhaps we should add this to the docs?

@SimenB
Copy link
Member

SimenB commented Oct 11, 2018

Ah, we've added an error message now! Nice.

I'm fine with adding a note in the FAQ or something, a lot of people want to use stuff in beforeAll/Each when defining tests (mostly because of async work). Having it in the docs makes sense to me!

EDIT: We should probably throw on empty arrays as well, not just non-arrays

@dandv
Copy link
Contributor

dandv commented Sep 3, 2019

FWIW, I've also run into this and expected beforeAll() to actually complete before test.each().

The documentation on test.each doesn't say anything about this.

@mattphillips
Copy link
Contributor

@dandv it's documented under troubleshooting - hope that helps

@ray-of-light
Copy link

ray-of-light commented Apr 25, 2020

If anyone needs to compute variables dynamically in beforeAll block, here is a way to do so: pass function references instead of values. Code example:

let values;

function getFirstValue() {
  return values[0];
}

function getSecondValue() {
  return values[1];
}

beforeAll(() => {
  // Values of the array are computed dynamically
  values = ['hello', 'world'];
});

describe('Test setting variables in beforeAll', () => {
  test.each([getFirstValue, getSecondValue])('parameterized', (valueFn) => {
    let value = valueFn();
    // the rest of the test code...
  })
});

If the data array is long, one could experiment with iterators like this:

let values;
let i = -1;

function getValue() {
  i++;
  return values[i];
}

beforeAll(() => {
  values = ['hello', 'world'];
});

describe('Test setting variables in beforeAll', () => {
  test.each([getValue, getValue])('parameterized', (valueFn) => {
    let value = valueFn();
    // the rest of the test code...
  })
});

@soullivaneuh
Copy link

Another example with a more complexe structure and Typescript:

test.each<[string, () => Partial<TransactionsData>, any]>([
  [
    'empty data',
    () => ({}),
    {
      type: {
        type: 'any.required',
      },
      amount: {
        type: 'any.required',
      },
      userId: {
        type: 'any.required',
      },
    },
  ],
  [
    'type and negative amount',
    () => ({
      // @ts-expect-error validation test
      type: 'foo',
      amount: -1,
      userId: customer1._id,
    }),
    {
      type: {
        type: 'any.required',
      },
      amount: {
        type: 'any.required',
      },
    },
  ],
  [
    'not existent user',
    () => ({
      type: 'credit',
      amount: 10,
      userId: 'not-existent'
    }),
    {
      userId: {
        type: 'any.not-found'
      },
    },
  ]
])(
  'admin creates a transaction with invalid %s',
  (_, data, expectedErrors) => assertInvalidData(
    app.service('kidsous-transactions').create(data()),
    expectedErrors,
  ),
);

As the submitted data is the only part where I need a variable define in beforeAll (customer1), I put a function only at this place.

This also allows me to keep raw data for the string representation of each case.

@github-actions
Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 10, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants