# vitest/valid-expect-in-promise

> Require a promise chain that contains `expect` to be awaited or returned from the test

A callback passed to `.then()`, `.catch()` or `.finally()` runs later. If the test doesn't await or return the promise, Vitest marks the test as passed before the `expect` in the callback runs, and a failed assertion doesn't fail the test.

{/* Generated by src/codegen/lint-rule-docs.ts. Do not edit this section. */}

## Configure

Off by default. To turn it on:

```toml bunfig.toml
[lint.rules]
"vitest/valid-expect-in-promise" = "error" # or "warn"
```

{/* End of the generated section. */}

## Examples

Reported:

{/* bad */}
```ts
import { expect, test } from "vitest";

test("loads the user", () => {
  loadUser(1).then((user) => {
    expect(user.name).toBe("Ada");
  });
});
```

A promise kept in a variable must be awaited or returned too:

{/* bad */}
```ts
import { expect, test } from "vitest";

test("loads the user", () => {
  const check = loadUser(1).then((user) => {
    expect(user.name).toBe("Ada");
  });
});
```

Code after the test's `return` never runs:

{/* bad */}
```ts
import { expect, test } from "vitest";

test("loads both users", () => {
  return loadUser(1).then((user) => {
    expect(user.name).toBe("Ada");
  });
  loadUser(2).then((user) => {
    expect(user.name).toBe("Grace");
  });
});
```

Not reported:

{/* good */}
```ts
import { expect, test } from "vitest";

test("loads the user", () => {
  return loadUser(1).then((user) => {
    expect(user.name).toBe("Ada");
  });
});

test("loads the admin", async () => {
  await loadUser(2).then((user) => {
    expect(user.role).toBe("admin");
  });
});

test("loads the guest", async () => {
  const user = await loadUser(3);
  expect(user.role).toBe("guest");
});
```

You can await several promises together:

{/* good */}
```ts
import { expect, test } from "vitest";

test("loads both users", async () => {
  const first = loadUser(1).then((user) => {
    expect(user.name).toBe("Ada");
  });
  const second = loadUser(2).then((user) => {
    expect(user.name).toBe("Grace");
  });
  await Promise.all([first, second]);
});
```

A test with a parameter isn't checked. This test takes the test context, so the rule misses the promise that nobody waits for:

{/* good */}
```ts
import { test } from "vitest";

test("loads the user", ({ expect }) => {
  loadUser(1).then((user) => {
    expect(user.name).toBe("Ada");
  });
});
```
