Have you ever heard about Snapshots being evil? About how fragile they are and how you should avoid them? It's true! You should be extremely careful about them because they do exact comparison of content as text, that is if you are snapshoting a component, you are actually snapshoting its HTML content, so anything changing the HTML will break the snapshot and if this is repeated too often, you may end up accidentally accepting snapshots updates and missing regressions in your application 😱.

But you don't have to snapshot the whole HTML! You can even provide a hint to recognize the snapshot and this can be used to generate tests fixtures on the flight in a very convening way, specially for very large content sets

Imagine you have a very big table and you want to test that given some props, the table renders the right content:

< table > < thead > < tr > < th v-for = "column in columns" > {{ column.name }} </ th > </ tr > </ thead > < tbody > < tr v-for = "item in items" > < td v-for = "column in columns" > < span class = "label" > {{ colum.name }}: </ span > < span class = "value" > {{ item[colum.key] }} </ span > </ td > </ tr > </ tbody > </ table >

Here columns is an array of all the columns in the table and items in an array of all the rows displayed. You could say both are props. If you want to test the content of the table given those props, you will have to test each row:

test( 'contains the right information' , () => { const wrapper = shallowMount(MyTable { props : { columns, items }}) expect(wrapper.find( 'thead th:nth-of-type(1)' ).text()).toBe( 'Product' ) expect(wrapper.find( 'tbody tr:nth-of-type(1) .value' ).text()).toBe( 'Dinner plates set of 8' ) })

There are multiple approaches to select the table cell like using a data-test attribute but that's not the issue here. Can we go faster when writing this kind of test? What if we wrote the component, check manually and then add a test that snapshots the current state?

test( 'contains the right information' , () => { const wrapper = shallowMount(MyTable { props : { columns, items }}) const cells = wrapper.findAll( "td" ); for ( let i = 0 ; i < cells.length; ++i) { const cell = cells.at(i); const label = cell.find( ".label" ); if (!label.exists()) continue ; expect(cell.find( ".value" ).text()).toMatchSnapshot(label.text()); } })

Writing this test will generate a snapshot the first time it is run:

exports[ `MyTable contains the right information: Product Name 1` ] = `"Dinner plates set of 8"` ; exports[ `MyTable contains the right information: Sells 1` ] = `"23"` ; exports[ `MyTable contains the right information: Stock 1` ] = `"3"` ;

The advantages of this solution is that adding a new column will create a single new snapshots without invalidating the others while removing existing columns will make some snapshot obsoletes and changing any of the cells .value content will make the snapshot test fail.

If you don't like the idea of creating dozens of snapshots like this, you can create some custom text value and create one single snapshot:

test( 'contains the right information' , () => { const wrapper = shallowMount(MyTable { props : { columns, items }}) const cells = wrapper.findAll( "td" ); let content = '' for ( let i = 0 ; i < cells.length; ++i) { const cell = cells.at(i); const label = cell.find( ".label" ); if (!label.exists()) continue ; content += ` ${label.text()} : ${cell.find( ".value" ).text()}

` } expect(content).toMatchSnapshot() })

You will end up with one single snapshot:

exports[ `MyTable contains the right information 1` ] = ` Product Name: Dinner plates set of 8 Sells: 23 Stock: 3 etc. ` ;

So remember: Snapshots can also be used to generate tests fixtures with text!

Happy Testing!