jest: [Bug]: Prettier v3 doesn't work with jest-snapshots

Version

29.6.1

Steps to reproduce

  1. Install prettier@3.0.0, which was just released yesterday
  2. Write a test that would generate an inline snapshot, like:
test('snapshot', () => {
  expect('abc').toMatchInlineSnapshot();
});

Expected behavior

The inline snapshot is updated

Actual behavior

Jest fails with

  ● Test suite failed to run

    TypeError: prettier.resolveConfig.sync is not a function

      at runPrettier (node_modules/jest-snapshot/build/InlineSnapshots.js:308:30)

Additional context

Prettier just released v3, which removed this line that added the sync function to resolveConfig. It looks like eslint-plugin-prettier ran into a similar problem. based on this issue.

Environment

System:
    OS: macOS 13.4.1
    CPU: (10) arm64 Apple M1 Pro
  Binaries:
    Node: 18.16.0 - ~/.nvm/versions/node/v18.16.0/bin/node
    npm: 9.5.1 - ~/.nvm/versions/node/v18.16.0/bin/npm
    pnpm: 8.5.1 - ~/Library/pnpm/pnpm
  npmPackages:
    jest: ^29.6.0 => 29.6.1

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 41
  • Comments: 25 (15 by maintainers)

Commits related to this issue

Most upvoted comments

It’ll be in Jest 30. Not sure when there’ll be a release, but within the next few weeks, hopefully 🙂

If we really need a synchronized version of prettier, and, since the inline snapshots formatting ain’t requiring good performances since intended to be rarely performed, why not just use the prettier executable and use execSync?

That’s pretty much what @prettier/sync does, but doesn’t work due to https://github.com/prettier/prettier-synchronized/issues/4#issuecomment-1649355749


Easiest would be to make toMatchInlineSnapshot async. But that’s horribly breaking 😅

Seems like it is possible to add prettierPath: null to Jest config. Formatting can be done using Prettier outside of Jest run. That can be a workaround until solution will be found.

Hum, do we really need that formatting? I always found it weird to format the contents of a template string with the code indentation since is is changing a const value in that code. In this case it is maybe a nice to have (but I think it is subjective), but considering it is a blocking feature, probably that getting rid of it won’t hurt that much.


What I did here in fact, not a big deal: https://github.com/nfroidure/metapak-nfroidure/blob/1ead42722e69c1db71d8c154718934ed32355b0e/src/eslint/package.test.ts#L156-L215

With the release of that, we should be able to integrate here.

I don’t have a firm date in mind, but I can probably do a prerelease.

Nightlies would be awesome (or CI publishing in general), but we don’t have that at the moment, unfortunately.

@SimenB Just curious about when/how the release process works to publish a new version with the changes merged in https://github.com/jestjs/jest/pull/14566, thanks!

The suggestion above is a good idea, but it may have some problematic side effects: if prettier and prettier-2 are installed in devDependencies of the same package, some package managers (definitely yarn 1, likely others too) will nondeterministically choose which prettier binary (from v2 or v3) to link under node_modules/.bin. So it may appear to work at first, but then cause errors or mysterious inconsistencies in CI or on someone else’s computer.

I wish I could think of a better way around this, but the best I can come up with is a postinstall script to fix the link if needed:

const path = require('path');
const fs = require('fs');

// TODO: Update this to point to your node_modules path relative to the script location
const nodeModulesPath = path.resolve(__dirname, 'node_modules');
const prettierBinPath = path.join(nodeModulesPath, '.bin/prettier');

if (fs.realpathSync(prettierBinPath).includes('prettier-2')) {
  fs.rmSync(prettierBinPath);
  const packageJson = JSON.parse(fs.readFileSync(path.join(nodeModulesPath, 'prettier/package.json'), 'utf-8'));
  const binFile =
    typeof packageJson.bin === 'string' ? packageJson.bin : packageJson.bin.prettier;
  const realBinPath = path.join(nodeModulesPath, 'prettier', binFile);
  fs.symlinkSync(realBinPath, prettierBinPath);
}

That module is currently broken (https://github.com/prettier/prettier-synchronized/pull/5), but I think it should work after that is released. We’ll then have to look at the version of prettier we load, and decide which API to use

I doubt we’ll ever support Prettier v3 as we need it to work synchronously.

However, we might be able to add support for @prettier/sync.