{"action":"created","issue":{"url":"https://api.github.com/repos/mochajs/mocha/issues/3457","repository_url":"https://api.github.com/repos/mochajs/mocha","labels_url":"https://api.github.com/repos/mochajs/mocha/issues/3457/labels{/name}","comments_url":"https://api.github.com/repos/mochajs/mocha/issues/3457/comments","events_url":"https://api.github.com/repos/mochajs/mocha/issues/3457/events","html_url":"https://github.com/mochajs/mocha/issues/3457","id":350750410,"node_id":"MDU6SXNzdWUzNTA3NTA0MTA=","number":3457,"title":"Mocha.run() callback called twice upon error with bail=true, after() hooks called second time","user":{"login":"mntnoe","id":705340,"node_id":"MDQ6VXNlcjcwNTM0MA==","avatar_url":"https://avatars1.githubusercontent.com/u/705340?v=4","gravatar_id":"","url":"https://api.github.com/users/mntnoe","html_url":"https://github.com/mntnoe","followers_url":"https://api.github.com/users/mntnoe/followers","following_url":"https://api.github.com/users/mntnoe/following{/other_user}","gists_url":"https://api.github.com/users/mntnoe/gists{/gist_id}","starred_url":"https://api.github.com/users/mntnoe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mntnoe/subscriptions","organizations_url":"https://api.github.com/users/mntnoe/orgs","repos_url":"https://api.github.com/users/mntnoe/repos","events_url":"https://api.github.com/users/mntnoe/events{/privacy}","received_events_url":"https://api.github.com/users/mntnoe/received_events","type":"User","site_admin":false},"labels":[{"id":210273,"node_id":"MDU6TGFiZWwyMTAyNzM=","url":"https://api.github.com/repos/mochajs/mocha/labels/unconfirmed-bug","name":"unconfirmed-bug","color":"995A44","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2018-08-15T09:51:11Z","updated_at":"2018-11-05T17:57:15Z","closed_at":null,"author_association":"NONE","body":"### Prerequisites\r\n\r\n- [x] Checked that your issue hasn't already been filed by cross-referencing [issues with the `faq` label](https://github.com/mochajs/mocha/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3Afaq%20)\r\n- [x] Checked next-gen ES issues and syntax problems by using the same environment and/or transpiler configuration without Mocha to ensure it isn't just a feature that actually isn't supported in the environment in question or a bug in your code.\r\n- [x] 'Smoke tested' the code to be tested by running it outside the real test suite to get a better sense of whether the problem is in the code under test, your usage of Mocha, or Mocha itself\r\n- [x] Ensured that there is no discrepancy between the locally and globally installed versions of Mocha. You can find them with: `node node_modules/.bin/mocha --version`(Local) and `mocha --version`(Global). We recommend avoiding the use of globally installed Mocha.\r\n\r\n### Description\r\nThe Mocha.prototype.run() callback is called twice upon error with bail set to true. Also, any remaining `after` hooks are only called second time. Hopefully the examples below are self explanatory.\r\n\r\nThis behavior gives issues when the Mocha.prototype.run() callback expects cleanup code to have run, and the callback may only be run once.\r\n\r\n### Steps to Reproduce\r\n\r\npackage.json:\r\n```\r\n{\r\n  \"dependencies\": {\r\n    \"mocha\": \"^5.2.0\"\r\n  }\r\n}\r\n```\r\nmocha.js\r\n```\r\nconst Mocha = require('mocha')\r\n\r\nconst mocha = new Mocha({ bail: true })\r\nmocha.addFile(`test.js`)\r\n\r\nmocha.run(failures => {\r\n    console.log('done')\r\n})\r\n```\r\ntest.js\r\n```\r\ndescribe('test', function() {\r\n    it('fails', function() {\r\n        throw new Error()\r\n    })\r\n    after(function() {\r\n        console.log('after')\r\n    })\r\n})\r\n```\r\n\r\n**Expected behavior:**\r\n\r\nnode mocha.js\r\n```\r\n  test\r\n    1) fails\r\nafter\r\n  0 passing (4ms)\r\n  1 failing\r\n  1) test\r\n       fails:\r\n  Error\r\n      at Context.<anonymous> (test.js:3:15)\r\ndone\r\n```\r\n\r\n**Actual behavior:** \r\n\r\nnode mocha.js\r\n```\r\n  test\r\n    1) fails\r\n  0 passing (4ms)\r\n  1 failing\r\n  1) test\r\n       fails:\r\n  Error\r\n      at Context.<anonymous> (test.js:3:15)\r\ndone\r\nafter\r\ndone\r\n```\r\n**Reproduces how often:** Every time.\r\n\r\n### Versions\r\nmocha 5.2.0\r\nnode-8.9.1\r\nnpm-6.0.1\r\n\r\n### Additional information\r\n\r\nMonkey patching Runner.prototype.emit to log calls gets this output:\r\n```\r\nevent: start\r\nevent: suite\r\nevent: suite\r\n  test\r\nevent: test\r\nevent: fail\r\n    1) fails\r\nevent: end\r\n\r\n  0 passing (3ms)\r\n  1 failing\r\n  1) test\r\n       fails:\r\n  Error\r\n      at Context.<anonymous> (test.js:3:15)\r\n\r\ndone\r\nevent: test end\r\nevent: hook\r\nafter\r\nevent: hook end\r\nevent: suite end\r\nevent: suite end\r\nevent: end\r\ndone\r\n```"},"comment":{"url":"https://api.github.com/repos/mochajs/mocha/issues/comments/435971481","html_url":"https://github.com/mochajs/mocha/issues/3457#issuecomment-435971481","issue_url":"https://api.github.com/repos/mochajs/mocha/issues/3457","id":435971481,"node_id":"MDEyOklzc3VlQ29tbWVudDQzNTk3MTQ4MQ==","user":{"login":"juergba","id":44573692,"node_id":"MDQ6VXNlcjQ0NTczNjky","avatar_url":"https://avatars1.githubusercontent.com/u/44573692?v=4","gravatar_id":"","url":"https://api.github.com/users/juergba","html_url":"https://github.com/juergba","followers_url":"https://api.github.com/users/juergba/followers","following_url":"https://api.github.com/users/juergba/following{/other_user}","gists_url":"https://api.github.com/users/juergba/gists{/gist_id}","starred_url":"https://api.github.com/users/juergba/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/juergba/subscriptions","organizations_url":"https://api.github.com/users/juergba/orgs","repos_url":"https://api.github.com/users/juergba/repos","events_url":"https://api.github.com/users/juergba/events{/privacy}","received_events_url":"https://api.github.com/users/juergba/received_events","type":"User","site_admin":false},"created_at":"2018-11-05T17:57:15Z","updated_at":"2018-11-05T17:57:15Z","author_association":"NONE","body":"#### Mocha.run() called twice: runner.js, line 245ff\r\n```\r\nthis.emit('fail', test, err);\r\n  if (this.suite.bail()) {\r\n    this.emit('end');\r\n  }\r\n};\r\n```\r\nThe `end` event must be called with the root suite in order to run Mocha.run() correctly. Above `this` is a child suite and the `end` event is emitted twice.\r\n\r\nMy suggestion is:\r\n```\r\nthis.emit('fail', test, err);\r\n  if (this.suite.bail()) {\r\n    // this.abort();\r\n    let rootSuite = this.parents().reverse()[0];\r\n    rootSuite.emit('end');\r\n```\r\nThis way Mocha.run() is called only once.\r\nI now have the problem that the `after`hook is executed, unfortunately the `abort()` doesn't show the expected effect. I'm open to any help how to skip this hook after a failed test."}}
{"actor":{"display_login":"juergba"}}