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

Promise returning matchers are not awaited if matcher has no async keyword. #2706

Closed
6 tasks done
hiyelbaz opened this issue Jan 18, 2023 · 0 comments · Fixed by #2707
Closed
6 tasks done

Promise returning matchers are not awaited if matcher has no async keyword. #2706

hiyelbaz opened this issue Jan 18, 2023 · 0 comments · Fixed by #2707

Comments

@hiyelbaz
Copy link

hiyelbaz commented Jan 18, 2023

Describe the bug

This breaks jest compatibility and prevents migrating some matcher extension libraries to vitest. Detailed example is below.

Reproduction

Vitest StackBlitz link: https://stackblitz.com/edit/vitest-dev-vitest-hwzkyd?file=test%2Fasync.test.js&initialPath=__vitest__
Jest StackBlitz link: https://stackblitz.com/edit/jest-example-kymfnr?file=async.test.js&terminal=test&view=editor


import { it, expect } from 'vitest';

//gets the value after 100ms asynchroniously
async function getAsyncResult() {
  return new Promise((resolve) => {
    setTimeout(() => resolve('expected result'), 100);
  });
}

// this matcher function has 'async' keyword and returns promise
async function toBeExpected_Original(text) {
  const { isNot } = this;
  const value = await getAsyncResult();
  const result = value === text;
  return {
    pass: isNot ? !result : result,
    message: () => `Input is ${result ? '' : 'not '}'expected result'`,
  };
}

// this matcher is the same function with toBeExpected_NonAsync but has 'async' keyword
async function toBeExpected_Async(text) {
  // ... process text before using the original matcher for some reason...
  // reuse the original matcher
  return toBeExpected_Original.call(this, text);
}

// this matcher function has no 'async' keyword but returns the promise from original matcher.
function toBeExpected_NonAsync(text) {
  // ... process text before using the original matcher for some reason...
  // reuse the original matcher
  return toBeExpected_Original.call(this, text);
}

const extensionMatchers = {
  toBeExpected_Original,
  toBeExpected_Async,
  toBeExpected_NonAsync,
};

expect.extend(extensionMatchers);

// OK
it('async matcher works as expected.', async () => {
  await expect('expected result').toBeExpected_Original();
});

// OK
it('async matcher that uses existing matcher works as expected.', async () => {
  await expect('expected result').toBeExpected_Async();
});

// NOT OK
it('sync but promise returning matcher fails.', async () => {
  await expect('expected result').toBeExpected_NonAsync();
});


System Info

System:
    OS: Windows 10 10.0.19044
    CPU: (16) x64 AMD Ryzen 7 PRO 4750U with Radeon Graphics
    Memory: 40.90 GB / 63.37 GB
  npmPackages:
    @vitejs/plugin-react: ^3.0.1 => 3.0.1
    vite: ^4.0.4 => 4.0.4
    vitest: ^0.27.1 => 0.27.1

Used Package Manager

npm

Validations

@github-actions github-actions bot locked and limited conversation to collaborators Jun 7, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants