Jest: beforeAll is being run even when it is inside xdescribe

Created on 15 Sep 2017  路  4Comments  路  Source: facebook/jest


Do you want to request a feature or report a bug?
Bug

What is the current behavior?
beforeAll is being run even when it is inside xdescribe

If the current behavior is a bug, please provide the steps to reproduce and either a repl.it demo through https://repl.it/languages/jest or a minimal repository on GitHub that we can yarn install and yarn test.

xdescribe('Testing blocking friends', () => {
  beforeAll(done => {
    console.log("This is appearing")
    done()
  })
})

What is the expected behavior?

xdescribe('Testing blocking friends', () => {
  beforeAll(done => {
    console.log("This should not appear")
    done()
  })
})

Please provide your exact Jest configuration and mention your Jest, node, yarn/npm version and operating system.

"devDependencies": {
    "jest": "^21.1.0"
}
"jest": {
    "testEnvironment": "node",
    "transform": {
      ".(ts|tsx)": "<rootDir>/node_modules/ts-jest/preprocessor.js"
    },
    "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
    "moduleDirectories": [
      "node_modules",
      "src"
    ],
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js",
      "json"
    ]
  }

Most helpful comment

This bug still persist, why this issue was closed?

For those interested, here's workaround patch, that ensures no beforeAll and afterAll are not run in skipped tests or when some others are marked with _only_.
It decorates global beforeAll and afterAll

Best is to load it in setup test file (one configured through setupTestFrameworkScriptFile setting)

// Decorate treeProcessor to detect whether test is disabled
// (due to other group/test being marked with "only")
const treeProcessor = require.requireActual('jest-jasmine2/build/tree_processor',
  { isInternalModule: true });
const origTreeProcessorFn = treeProcessor.default;
treeProcessor.default = function treeProcessor(options) {
  const runnableIds = options.runnableIds;
  const tree = options.tree;
  const isDirectlyEnabled = (node, parentEnabled) =>
    (node._isEnabled = parentEnabled || runnableIds.indexOf(node.id) !== -1);
  const resolveEnabled = (node, enabled) => {
    if (!node.children || !node.children.length) return;
    let hasChildEnabled = false;
    node.children.forEach(child => {
      resolveEnabled(child, isDirectlyEnabled(child, enabled));
      if (child._isEnabled) hasChildEnabled = true;
    });
    if (!node._isEnabled && hasChildEnabled) {
      node._isEnabled = true;
      node.children.forEach(child => {
        if (child._isBeforeAfterHack) child._isEnabled = true;
      });
    }
  };
  resolveEnabled(tree, isDirectlyEnabled(tree, false));
  return origTreeProcessorFn.call(this, options);
};

// Dummy spec retriever (allows to detect whether parent group is skipped)
const getDummySpec = () => {
  const spec = global.jasmine.getEnv().describe('ignore', Function.prototype);
  spec._isBeforeAfterHack = true;
  spec._parentMarkedPending = spec.markedPending;
  spec.markedPending = true;
  spec.onException = () => {};
  return spec;
};

const decorateBeforeAfter = name => {
  const originalFn = global[name];
  global[name] = function (fn, ...args) {
    const tmpSpec = getDummySpec();
    if (tmpSpec._parentMarkedPending) return null;
    return originalFn.call(this, Object.defineProperty(function (done, ...args) {
      if (tmpSpec._isEnabled === false) {
        if (done) done();
        return null;
      }
      return fn.call(this, done, ...args);
    }, 'length', { configurable: true, value: fn.length }), ...args);
  };
};
decorateBeforeAfter('beforeAll');
decorateBeforeAfter('afterAll');

All 4 comments

This may be related to #4166

Yup, looks like the same thing. I'll just notify @aaronabramov so he's aware of it.

This bug still persist, why this issue was closed?

For those interested, here's workaround patch, that ensures no beforeAll and afterAll are not run in skipped tests or when some others are marked with _only_.
It decorates global beforeAll and afterAll

Best is to load it in setup test file (one configured through setupTestFrameworkScriptFile setting)

// Decorate treeProcessor to detect whether test is disabled
// (due to other group/test being marked with "only")
const treeProcessor = require.requireActual('jest-jasmine2/build/tree_processor',
  { isInternalModule: true });
const origTreeProcessorFn = treeProcessor.default;
treeProcessor.default = function treeProcessor(options) {
  const runnableIds = options.runnableIds;
  const tree = options.tree;
  const isDirectlyEnabled = (node, parentEnabled) =>
    (node._isEnabled = parentEnabled || runnableIds.indexOf(node.id) !== -1);
  const resolveEnabled = (node, enabled) => {
    if (!node.children || !node.children.length) return;
    let hasChildEnabled = false;
    node.children.forEach(child => {
      resolveEnabled(child, isDirectlyEnabled(child, enabled));
      if (child._isEnabled) hasChildEnabled = true;
    });
    if (!node._isEnabled && hasChildEnabled) {
      node._isEnabled = true;
      node.children.forEach(child => {
        if (child._isBeforeAfterHack) child._isEnabled = true;
      });
    }
  };
  resolveEnabled(tree, isDirectlyEnabled(tree, false));
  return origTreeProcessorFn.call(this, options);
};

// Dummy spec retriever (allows to detect whether parent group is skipped)
const getDummySpec = () => {
  const spec = global.jasmine.getEnv().describe('ignore', Function.prototype);
  spec._isBeforeAfterHack = true;
  spec._parentMarkedPending = spec.markedPending;
  spec.markedPending = true;
  spec.onException = () => {};
  return spec;
};

const decorateBeforeAfter = name => {
  const originalFn = global[name];
  global[name] = function (fn, ...args) {
    const tmpSpec = getDummySpec();
    if (tmpSpec._parentMarkedPending) return null;
    return originalFn.call(this, Object.defineProperty(function (done, ...args) {
      if (tmpSpec._isEnabled === false) {
        if (done) done();
        return null;
      }
      return fn.call(this, done, ...args);
    }, 'length', { configurable: true, value: fn.length }), ...args);
  };
};
decorateBeforeAfter('beforeAll');
decorateBeforeAfter('afterAll');

This is an issue for me. I naively tried to comment out a block of tests by changing describe to xdescribe, and the beforeAlls still run.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

hramos picture hramos  路  3Comments

samzhang111 picture samzhang111  路  3Comments

kgowru picture kgowru  路  3Comments

jardakotesovec picture jardakotesovec  路  3Comments

benmccormick picture benmccormick  路  3Comments