Skip to content

After and AfterSuite hooks return exit code 0 on failure instead of 1, incorrectly indicating success #5057

Closed

Description

@h2oJan

What are you trying to achieve?

When an error is thrown inside an After or AfterSuite hook in CodeceptJS, the process should exit with a non-zero exit code (e.g. 1), indicating failure.

What do you get instead?

Process exits with code 0, indicating success. This misleads CI systems and users, as the test run should be considered failed when any lifecycle hook fails.
This worked correctly in CodeceptJS 3.6.6.
It also works correctly for Before and BeforeSuite hooks.

Reproduction steps

Feature('after-hook');

Before(({ I }) => {
    I.amOnPage('https://www.google.com')
    I.waitForText('Google')
})

After(({ I }) => {
    I.waitForText('Google-xxx-FAIL') // This will fail
})

Scenario('test something',  ({ I }) => {
    I.waitForText('Google')
})

To obtain exit code, you can run with npm run codeceptjs; echo "Exit code: $?"

Details

  • CodeceptJS version: 3.7.3
  • Working CodeceptJS version: 3.6.6
  • Helper: Playwright
  • NodeJS version: 24.3.0
  • Operating System: MacOS

Activity

  1. nikzupancic commented on Aug 5, 2025

    @nikzupancic
    Contributor

    I wanted to open a PR for this but based on the current implementation it almost seems like this is the intended behavior?

    This started with version 3.7.0. Previous implementation emits event.test.failed for the whole suite, regardless of which hook failed. Maybe not the ideal implementation since it's mixing up test and suite concepts

    recorder.cleanAsyncErr();
    event.emit(event.test.failed, suite, err);
    if (hookName === 'after') event.emit(event.test.after, suite);
    if (hookName === 'afterSuite') event.emit(event.suite.after, suite);

    The new version fixes the suite and test differences with suiteTestFailedHookError but it's only triggered for before and beforeSuite failures

    recorder.cleanAsyncErr()
    if (hookName == 'before' || hookName == 'beforeSuite') suiteTestFailedHookError(suite, err, hookName)
    if (hookName === 'after') suite.eachTest(test => event.emit(event.test.after, test))
    if (hookName === 'afterSuite') event.emit(event.suite.after, suite)

    In my opinion suiteTestFailedHookError should be called for any hook failure, like this was done before, otherwise a failed after hook will just silently skip all the remaining tests and never indicate any problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions