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

Configurable snapshots directory for colocated tests #1650

Closed
holic opened this issue Sep 8, 2016 · 66 comments
Closed

Configurable snapshots directory for colocated tests #1650

holic opened this issue Sep 8, 2016 · 66 comments

Comments

@holic
Copy link

holic commented Sep 8, 2016

The React community seems to be moving towards colocating tests with components. I appreciate the changes to the default testRegex that looks for any .test.js file.

However, using this colocation method means a bunch of scattered __snapshots__ directories throughout the codebase. Since snapshots seem to be more for machine readability than human readability, I would tend to throw them all in a single top-level directory (like you might have for build/dist files). What are your thoughts on making the snapshots directory configurable?

@holic holic changed the title Changing snapshots directory for colocated tests Configurable snapshots directory for colocated tests Sep 8, 2016
@cpojer
Copy link
Member

cpojer commented Sep 8, 2016

snapshots are colocated with tests and they are definitely not meant to be for machine readability. They are meant to be reviewed by humans, both the author of a test and the code reviewers.

@cpojer
Copy link
Member

cpojer commented Sep 8, 2016

Jest also ensures that there are never any stale snapshots in the system. This means we both need a way to map from a snapshot to its associated test and back. This seems kinda hard to configure via string values in the JSON config :(

@holic
Copy link
Author

holic commented Sep 8, 2016

Thanks for the quick reply!

I understand that the snapshots are meant to be read and reviewed. It just seems a bit messy to have __snapshots__ littered throughout the codebase when I want to have tests colocated with components. This may also come from a pattern of grouping components by functionality, rather than having a components directory (e.g. user/Profile.js and layout/Nav.js).

In the meantime, I've just started dropping tests into __tests__ to get the __snapshots__ into a single place but this isn't my ideal.

I also understand this is a bit hard to configure. My thought was to define some top level directory for __snapshots__ and have the directory structure within it match the path to the component from that top level.

It might just be me that finds this messy. Curious to hear from others that colocate tests with components and have multiple directories of components.

@cpojer
Copy link
Member

cpojer commented Sep 8, 2016

I don't really quite understand what you mean. The snapshots are colocated with tests and there is a 1:1 mapping between testfilename.js and __snapshots__/testfilename.js.snap?

@holic
Copy link
Author

holic commented Sep 8, 2016

Currently my directory looks a bit like this:

js/
  user/
    __snapshots__/
      Avatar.test.js.snap
      Profile.test.js.snap
    Avatar.js
    Avatar.test.js
    Profile.js
    Profile.test.js
  layout/
    __snapshots__/
      App.test.js.snap
      Nav.test.js.snap
    App.js
    App.test.js
    Nav.js
    Nav.test.js

The __snapshots__ in this way feels a little messy to me (but this may just be me).

As an alternative, my thought was a directory structure like this might be easier to understand/comb through:

js/
  __snapshots__/
    user/
      Avatar.test.js.snap
      Profile.test.js.snap
    layout/
      App.test.js.snap
      Nav.test.js.snap
  user/
    Avatar.js
    Avatar.test.js
    Profile.js
    Profile.test.js
  layout/
    App.js
    App.test.js
    Nav.js
    Nav.test.js

@cpojer
Copy link
Member

cpojer commented Sep 8, 2016

but that is the opposite of colocating snapshot files with their tests, isn't it?

@holic
Copy link
Author

holic commented Sep 8, 2016

I'm proposing that the snapshots don't necessarily need to be colocated with tests. I find it more important that tests are colocated with components. Having all three colocated feels messy, mostly due to the several __snapshots__ directories that are created/scattered throughout the codebase (at least in the way I've chosen to organize my components).

@cpojer
Copy link
Member

cpojer commented Sep 8, 2016

I'm not religiously opposed to this if you want to do all the work necessary to support this, find a way to make this maintainable and test it well.

@cpojer
Copy link
Member

cpojer commented Sep 8, 2016

We can also help on our discord channel and happy to review code, of course :)

@holic
Copy link
Author

holic commented Sep 8, 2016

I think my main argument is that the snapshots are auto generated and aren't meant to be modified manually, nor really imported directly into the codebase. So it doesn't feel right to have them intermixed within the code which you are actively editing/maintaining/importing.

I'm not particularly married to this idea either :) Just wanted to propose it to see what others thought. If I'm not alone in this, I may take the time to mock up a PR and see what it might look like.

@cpojer
Copy link
Member

cpojer commented Sep 8, 2016

I'm sure you find many people that share your opinion. Testing is like a religion to people and I'm happy to support all kinds of doing this as long as it integrates well with Jest and is well tested itself.

@cpojer
Copy link
Member

cpojer commented Sep 14, 2016

This is something where we'll need some help from the community. I think a good way to support this is by adding a config option resolveSnapshots that points to a module with two functions:

exports.resolveSnapshotFile = testPath => snapshotFilePath;
exports.resolveTestFile = snapshotFilePath => testPath;

this way we can call these methods to resolve the snapshot path from a test path and the other way round and it will enable use to keep snapshot files consistent.

@cpojer
Copy link
Member

cpojer commented Nov 14, 2016

I'm gonna close this given the inactivity. If somebody would like to work on this, I'm happy to reopen this and review a PR :)

@cpojer cpojer closed this as completed Nov 14, 2016
@develar
Copy link
Contributor

develar commented Dec 1, 2016

I have the same problem as #1653.

preprocessor approach is not good in case of

  1. TypeScript and IntelliJ IDEA.

    Because IntelliJ IDEA has built-in very fast TS compiler. So, during editing no compiler output. And you add "Compile TypeScript" task to run configuration — output will be dumped from memory to FS on run. No need to use slow (because ts must operate on the whole project, — opposite to babel) runtime preprocessor.

  2. TypeScript on CI server.
    Because on CI server in any case you compile all sources before test run — again because TS / tslint operates on the whole project, not on individual file.

Well, as a workaround, out/__snapshots__ can be added to VCS.

@lucasfeliciano
Copy link

lucasfeliciano commented Feb 13, 2017

👀
Following this to work on it in a near future

@cpojer
Copy link
Member

cpojer commented Feb 13, 2017

Actually at this point I don't really think I want to support this feature. It adds unnecessary complexity and gives almost no value.

@luispuig
Copy link

So. How did end it?. I really like to have each test with its component. But I'd prefer to get all snapshot file in a unique folder, not around the code.

@lucasfeliciano
Copy link

Yeah, I think would be good to have this feature.
I'm not 100% happy with my snapshots all over the project. :(

@luispuig
Copy link

And I don't like either to replicate the project structure on test folder...

@porto88
Copy link

porto88 commented Mar 2, 2017

+1, I would also like to have all snapshots moved to one folder.

@lucasfeliciano
Copy link

Cool, I'll try to work on it this weekend and propose a PR.

Then we move this discussion there.

@luispuig
Copy link

luispuig commented Mar 3, 2017

Great!

Let me know if I can help you. I've been thinking about complexity.

The main problem is what happens if there are Test with same file name. Probably best option would be to get relative path of test file and replicate folder structure on snapshot folder.

@luispuig
Copy link

luispuig commented Mar 3, 2017

@cpojer told me that @ljharb was interested on this feature too.

@andreyluiz
Copy link

@lucasfeliciano @luispuig Any progress on this? Do yout want some help with something?

@kkutsner
Copy link

kkutsner commented Dec 12, 2017

Let's say I have service A and service B that expose identical REST API. I want tests for both services and I want to use snapshots feature to store some filtered JSON response returned by service A and service B. Let's say I have written tests once that may hit one service at time (A or B). I can run them against service A, get snapshots, then I can run them against service B and get new snapshots. It turns out that service A and service B may produce different snapshots for some known reasons. So it sounds reasonable to specify different snapshots locations depending on what service is tested. Because I can't do it through Jest config, I have to maintain copy of the same test stored in the different folder, but I really want to have just one test and two different snapshots.

I hope this sounds like a real use case to get it supported. I can see it is a rare case, but I think it is related to other cases that people brought here. Thanks!

@asn007
Copy link

asn007 commented Jan 24, 2018

Looks like there's no progress on this. I would love to try working on it, since I need this feature badly

@astrotim
Copy link

astrotim commented Feb 6, 2018

@joshduck they don't wanna see ↑

@sidferreira
Copy link

@cpojer Disagree, for React Native projects, which we can have more than one platform, is really useful. Check the rendering of the component on iOS, Android, and whatever else show up. Just a way to override the 'SNAP' extension would help a lot already.

@RyanCavanaugh
Copy link

This is really unfortunate if you're using a setup where you have source files (e.g. TypeScript) which are checked in and output files (e.g. the corresponding JS) which aren't checked in. The snapshot files end up in a normally-.gitignore'd directory.

@eluchsinger
Copy link

So much clutter without this function...

@kkutsner
Copy link

Snapshots are driving my project. Without this function I’m forced to build my own solution, which eliminates the need of using Jest... Bummer.

@hiredgun
Copy link

hiredgun commented Mar 20, 2018

I don't like the idea of having __snapshots__ directory colocated with every test too and I would rather prefer to have an option to place all of them in a single directory e.g. on the top level. To me, it's just a visual thing and IMHO hundreds of __snapshots__ dirs scattered on a files tree looks really messy. Fortunately, there's a simple workaround for this in VS Code - just exclude __snapshots__ directory from the files explorer in your settings like this:

    "files.exclude": {
        "**/__snapshots__": true
    }

This way __snapshots__ directory will be hidden in the files explorer in your VS Code. I guess sth similar is also possible in Jetbrains' IDEs.

@viddo
Copy link
Contributor

viddo commented May 6, 2018

I spent a few hours looking into this, put up a PR #6143 based on a previous suggestion for anyone that's interested.

@akuji1993
Copy link

Seems like you are moving foward with this @viddo. Thanks for your work on this, I'd really like to see this get merged.

@holic
Copy link
Author

holic commented Nov 2, 2018

Thanks @viddo! 😍

@SimenB
Copy link
Member

SimenB commented Nov 3, 2018

This has landed and will be available in Jest 24. It's currently available by installing jest@beta

@rattrayalex-stripe
Copy link

In case others find it helpful, here is the contents of my snapshotResolver.js implementing @assertchris 's suggestion:

// https://jestjs.io/docs/en/configuration.html#snapshotresolver-string
module.exports = {
  testPathForConsistencyCheck: 'some/example.test.js',

  resolveSnapshotPath: (testPath, snapshotExtension) =>
    testPath.replace(/\.test\.([tj]sx?)/, `${snapshotExtension}.$1`),

  resolveTestPath: (snapshotFilePath, snapshotExtension) =>
    snapshotFilePath.replace(snapshotExtension, '.test'),
}

This results in

component.ts
component.test.ts
component.snap.ts

@turtlebe
Copy link

turtlebe commented Mar 5, 2020

If you want to place test files (*.test.js) next to the relevant components but place snapshots in a single directory (__snapshots__), you can do like this.

// jest.config.js
module.exports = {
... ...
snapshotResolver: './__snapshots__/snapshotResolver.js',
... ...
}

// snapshotResolver.js

module.exports = {
resolveSnapshotPath: (testPath, snapshotExtension) =>
testPath
.replace(/.test.([tj]sx?)/, '.test' + snapshotExtension)
.replace(/src([/\\]components)/, '__snapshots__'),

resolveTestPath: (snapshotFilePath, snapshotExtension) =>
snapshotFilePath.replace(snapshotExtension, '.js').replace('__snapshots__', 'src/components'),

testPathForConsistencyCheck: 'src/components/some.test.js',
}

@github-actions
Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 11, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests