eddyerburgh / jest-serializer-vue Goto Github PK
View Code? Open in Web Editor NEWJest Serializer for Vue components
License: MIT License
Jest Serializer for Vue components
License: MIT License
First of all, thank you for your contribution.
I am using jest snapshot for snapshoting template state of Vue component - SFC (single file component) and instanbul comments get into template and so it breaks snapshots. I think it is Vue loader or something which replaces controller functions references in templates with their implementation. Maybe serializer would removesuch javascript code from templates? ๐ ๐คท
template source look like this:
<h6>{{ $t('user.profile.title') }}</h6>
<ws-input
v-model="newUser.personalInformation.login"
name="username"
:label="$t('user.login.label')"
autocomplete="username"
path="user.personalInformation.login"
debounce="300"
required
:lazy-rules="false"
restrict="0-9A-Za-z\-\."
:rules="[required, minLength(2), maxLength(125), uniqueLogin]"
/>
Thank you for any help ๐
Hey there! ๐
I needed to add some functionality today that replaces random attributes with deterministic ones. Specifically, I am working with v-tooltip, which generates random ids that end up in the component's HTML.
I essentially needed to add a line after this one that was something to the effect of html = standardizeRandomIDs(html)
, but your library currently doesn't expose a way to add that functionality.
I had to copy your library to a local file and add the custom replace myself. ๐ข
Would you consider opening up your print
method to optionally take a callback that defines custom replace logic? Something like:
module.exports = {
// test (received) { ... },
print (received, cb) {
let html = (isVueWrapper(received) ? received.html() : received) || ''
html = removeServerRenderedText(html)
html = removeDataTestAttributes(html)
if(cb) html = cb(html)
return beautify(html, { indent_size: 2 })
}
}
That way, I could have a least imported it and created a wrapper around it instead of copying and pasting all the code over to make the edits.
What do you think?
Hi,
any idea how I could make such output in the snapshot?
<routerlink-stub to="{ to: "home" }">Home</routerlink-stub>
That is the current behaviour.
<routerlink-stub to="[object Object]">Home</routerlink-stub>
Hey !
Actually the library is not able to serialize Vue 3 component, even when embed in a VueWrapper (from @vue/test-utils
, right ?).
The trick I used to "extract" the template from the Vue 3 wrapper :
import {shallowMount} from "@vue/test-utils";
import MyComp from "../MyComp.vue";
describe("Vue 3 component", () => {
it("should test with a snapshot", () => {
const component = shallowMount(MyComp, {});
expect(component.__app._container).toMatchSnapshot();
});
});
By doing this trick, I actually have a readable snapshot :
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Vue 3 component should test with a snapshot 1`] = `
<div
data-v-app=""
>
<div
class="container"
>
<h2>
Weeeew, this is my comp !
</h2>
</div>
</div>
`;
If I don't use this trick, the whole VueWrapper instance is serialized as an object, with all properties and methods.
Hey Edd!
Any chance of the breaking change details for 2.0.0
being a little more detailed? There's nothing in the CHANGELOG.md
and the Releases page is a bit vague.
There is an example in the Readme:
import { shallow } from '@vue/test-utils'
shallow
should be changed to shallowMount
, because there is no shallow
in @vue/test-utils
Components that result in no .html()
result in an error attempting to call replace
on undefined
.
I think the case could be made that wrapper.html()
should always return a string, but that might be outside the scope of handling this inconsistency within the serializer.
I see 2 possible solutions:
Check for undefined here in the serializer and return an empty string instead
Ensure a string is returned by wrapper.html()
always. An empty string in this case.
Would be open to submit a PR for either option.
Vue 2.6.0+ recommends v-slot
instead of slot
attribute.
https://vuejs.org/v2/guide/components-slots.html#Named-Slots-with-the-slot-Attribute
But jest-serializer-vue
don't support it and using it causes an error.
The actual error messages I encountered are listed below:
I'm using these versions:
FAIL test/index.spec.ts
โ Test suite failed to run
Jest encountered an unexpected token
This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
Here's what you can do:
โข To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
โข If you need a custom transformation specify a "transform" option in your config.
โข If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html
Details:
SyntaxError: Unexpected token (1:839)
1 : function render () {with(this){return _c('main',{staticClass:"column main"},[_c('organized-breadcrumbs',{attrs:{"org-path":orgPath,"org-title":orgTitle}},[_c('li',[_c('a',[_v("Business")])]),_c('li',[_c('nuxt-link',{attrs:{"to":termsPath}},[_v("ๅฉ็จ่ฆ็ดๆๆธ")])],1),_c('li',{staticClass:"is-active"},[_c('a',{attrs:{"aria-content":"page"}},[_v(_s(title))])])]),_c('business-tabs',{attrs:{"org":org,"active":"terms"}},[_c('template',{slot:"terms"},[_c('term-document',{attrs:{"title":title,"original-body":original.body,"body":body,"is-processing":isProcessing,"enable-button":hasDiff,"services":services,"is-editting":true,"can-save":canSave,"can-remove":canRemove},on:{"update:title":function($event){title=$event},"update:body":function($event){body=$event},"save":save,"remove":removeConfirm},scopedSlots:_u([{key:"service-list",fn:function(v-slot:service-list){return _l((services),function(service){return _c('b-tag',{key:service.id,attrs:{"type":"is-info"}},[_v(_s(service.groupRef.name)+" / "+_s(service.name))])})}}])})],1)],2)],1)}}
^
at Parser.pp$4.raise (node_modules/vue-template-es2015-compiler/buble.js:2757:13)
at Parser.pp.unexpected (node_modules/vue-template-es2015-compiler/buble.js:647:8)
at Parser.pp.expect (node_modules/vue-template-es2015-compiler/buble.js:641:26)
at Parser.pp$2.parseBindingList (node_modules/vue-template-es2015-compiler/buble.js:1694:19)
at Parser.pp$1.parseFunctionParams (node_modules/vue-template-es2015-compiler/buble.js:1231:22)
at Parser.pp$1.parseFunction (node_modules/vue-template-es2015-compiler/buble.js:1218:8)
at Parser.pp$3.parseExprAtom (node_modules/vue-template-es2015-compiler/buble.js:2184:17)
at Parser.<anonymous> (node_modules/vue-template-es2015-compiler/buble.js:6003:24)
at Parser.parseExprAtom (node_modules/vue-template-es2015-compiler/buble.js:6129:31)
at Parser.pp$3.parseExprSubscripts (node_modules/vue-template-es2015-compiler/buble.js:2047:19)
passing object to prop of one component should be serialized
serializing following component:
<template>
<div>
<custom-component :data="{a: true}">
</div>
</template>
gives you somehting like this:
exports[`InstantOrderForm snapshot renders 1`] = `
<div>
<custom-component-stub data="[object Object]">
</div>
can this be fixed? am I doing something wrong?
I would like to keep data="{a: true}"
in snapshot
Conditional components that are false render as a comment: <!---->
jest-vue-serializer should strip these out for an improved diff.
(Original issue vuejs/vue-test-utils#792)
Since forking jest-serializer-vue
I've essentially rewrote the entire repo. This includes changing things like the CI, and code style, with very different linting settings. I've also restructured the files. Making a direct PR against this repo would likely be undesired by the maintainer. However, unless the Vue core team wants to adopt my version, the majority of people using Vue will automatically inherit this version. I'd like to see this version improved to include the same features I've already implemented in my fork.
Feature Parity Tracker:
data-server-rendered
data-test
#16data-test-id
data-testid
data-qa
(disabled by default)data-v
ID'stest
(disabled by default)test
(disabled by default)[object Object]
#17The default options shipped in jest-serializer-vue
make snapshots and snapshot diffs pretty unreadable half the time.
Input code like this:
<template>
<div data-test="baseTitle">
<h3 class="inline-block">{{ title }}</h3>
<span v-show="showSpinner">
<i class="fa fa-spinner fa-pulse fa-lg fa-fw"></i>
<span class="sr-only">Loading...</span>
</span>
<router-link
v-if="createNewRouteName"
:to="{
name: createNewRouteName,
params: {
id: 'new'
}
}"
>
<button :disabled="disableCreateNew" type="button" class="primary">
<i class="fa fa-plus"></i>
Create New
</button>
</router-link>
</div>
</template>
Will output code like this:
<div>
<h3 class="inline-block">Create New and Spinner</h3> <span><i class="fa fa-spinner fa-pulse fa-lg fa-fw"></i> <span class="sr-only">Loading...</span></span> <a><button type="button" class="primary"><i class="fa fa-plus"></i>
Create New
</button></a>
</div>
If you change the options passed into pretty
, you can get this:
<div>
<h3 class="inline-block">Create New and Spinner</h3>
<span>
<i class="fa fa-spinner fa-pulse fa-lg fa-fw"></i>
<span class="sr-only">Loading...</span>
</span>
<a>
<button type="button" class="primary">
<i class="fa fa-plus"></i>
Create New
</button>
</a>
</div>
Here is a comparison of a diff generated using the default jest-serializer-vue
and my custom options.
Note: This is for a simple, 25 line, template. Imagine a longer, more complex diff, like in a table component with lots of rows of data that have custom markup logic in each cell.
I've changed the serializer on all my projects to a custom one, based on jest-serializer-vue
to have these easier to read snapshots.
// Based on jest-serializer-vue
const beautify = require('pretty');
function isHtmlString (received) {
return received && typeof(received) === 'string' && received.startsWith('<');
}
function isVueWrapper (received) {
return received && typeof(received) === 'object' && typeof(received.isVueInstance) === 'function';
}
function removeServerRenderedText (html) {
return html.replace(/ data-server-rendered="true"/, '');
}
// This removes data-test="whatever" from your snapshots
// If you also want to remove them from your production builds, see:
// https://forum.vuejs.org/t/how-to-remove-attributes-from-tags-inside-vue-components/24138
function removeDataTestAttributes (html) {
// [-\w]+ will catch 1 or more instaces of a-z, A-Z, 0-9, hyphen (-), or underscore (_)
return html.replace(/ data-test="[-\w]+"/g, '');
}
module.exports = {
test: function (received) {
return isHtmlString(received) || isVueWrapper(received);
},
print: function (received) {
let html = received || '';
if (isVueWrapper(received)) {
html = received.html();
}
html = removeServerRenderedText(html);
html = removeDataTestAttributes(html);
// To see available options: https://github.com/beautify-web/js-beautify/blob/master/js/src/html/options.js
const options = {
indent_char: ' ',
indent_inner_html: true,
indent_size: 2,
inline: [],
sep: '\n',
unformatted: ['code', 'pre']
};
return beautify(html, options);
}
};
Adopting the same options in the official jest-serializer-vue
will have much better default snapshots (though will break people's existing snapshots, so it should be a major bump if adopted). Though I would find it preferable to make these options modifiable in some way, so user's can tweak them without having to basically duplicate the same file, losing downstream updates, just to change an option. And from the other perspective it would allow people to opt out of changes in these options in the future by passing in their own overrides if they change again, making breaking changes of the future less painful.
Is it possible to change the output directory?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.