rspec-snapshot icon indicating copy to clipboard operation
rspec-snapshot copied to clipboard

Making the snapshot name optional

Open hooptie45 opened this issue 8 years ago • 7 comments

In jest, if you can omit the snapshot name; it'll derive it from the example name. Is that behavior supported? If it isn't, I'd be happy to help build that support. Thoughts?

hooptie45 avatar Jun 08 '17 17:06 hooptie45

PR is welcome.

yesmeck avatar Jun 09 '17 08:06 yesmeck

Is this being worked on? If not, I'll probably add this early next week.

tncbbthositg avatar Jun 29 '17 14:06 tncbbthositg

@tncbbthositg Welcome PR!

yesmeck avatar Jul 04 '17 01:07 yesmeck

Seconded!

rrcobb avatar Jan 19 '18 18:01 rrcobb

This would be a great feature. Is RSpec.current_example.description the correct way to access this metadata from within the matcher?

edmorley avatar Jan 03 '21 14:01 edmorley

Agree that this would be a useful feature. The way jest does it is to use the spec file name as the snapshot name and then treat the snapshot file like a hash using the example descriptions as the keys.

Will put this on the roadmap for the next version

levinmr avatar Jun 22 '21 14:06 levinmr

vcr has a common pattern for generating names of cassettes from the rspec example.

# probably already have this in the code
example = RSpec.current_example

# get the description (name) or the scoped id (like 1:2:4:8) 
path_data = [example.metadata[:description] || example.metadata[:scoped_id]]
parent = example.example_group

base_path = ""
while parent != RSpec::ExampleGroups
  base_path = File.dirname(parent.file_path.gsub("./spec/", ""))

  path_data << parent.metadata[:description]
  parent = parent.module_parent
end

path_data << base_path if base_path.present?

# Need to do this differently since it's a Rails thing
path_data = path_data.map { ActiveStorage::Filename.new(_1).sanitized }

# path_data is ['renders_component', 'when rating is > 0', 'StarRatingComponent', 'components']
name = path_data.reverse.join("/")

expect(rendered_component).to match_snapshot(name)

Will output a file to

spec/components/__snapshots__/components/StarRatingComponent/when rating is > 0/renders component.snap

although I have all of my snapshots going to spec/snapshots so it's

spec/snapshots/components/StarRatingComponent/when rating is > 0/renders component.snap

There's also another common vcr-ism that is probably nicer for the default folder setup:

name =
  RSpec.current_example
        .metadata[:full_description]
        .split(/\s+/, 2)
        .join("/")
        .underscore.tr(".", "/")
        .gsub(%r{[^\w/]+}, "_")
        .gsub(%r{/$}, "")

that results in

./spec/components/__snapshots__/star_rating_component/when_rating_is_0_renders_component.snap

This one can have collisions though, for example if you had a context "when rating is >= 0" and "when rating is < 0" the names would be the same because it's aggressive about stripping characters regardless of safety. This issue could be fixed by sanitizing the name like ActiveStorage::Filename so it doesn't strip out meaningful but filename-safe characters. (surprisingly, Ruby's stdlib doesn't have a filename sanitizer.)

bbugh avatar Feb 22 '22 19:02 bbugh