vue3-yuanma/packages/server-renderer/__tests__/ssrRenderAttrs.spec.ts

185 lines
3.8 KiB
TypeScript

/**
* @jest-environment node
*/
import {
ssrRenderAttrs,
ssrRenderClass,
ssrRenderStyle,
ssrRenderAttr
} from '../src/helpers/ssrRenderAttrs'
import { escapeHtml } from '@vue/shared'
describe('ssr: renderAttrs', () => {
test('ignore reserved props', () => {
expect(
ssrRenderAttrs({
key: 1,
ref_key: 'foo',
ref_for: 'bar',
ref: () => {},
onClick: () => {}
})
).toBe('')
})
test('normal attrs', () => {
expect(
ssrRenderAttrs({
id: 'foo',
title: 'bar'
})
).toBe(` id="foo" title="bar"`)
})
test('empty value attrs', () => {
expect(
ssrRenderAttrs({
'data-v-abc': ''
})
).toBe(` data-v-abc`)
})
test('escape attrs', () => {
expect(
ssrRenderAttrs({
id: '"><script'
})
).toBe(` id="&quot;&gt;&lt;script"`)
})
test('boolean attrs', () => {
expect(
ssrRenderAttrs({
checked: true,
multiple: false,
readonly: 0,
disabled: ''
})
).toBe(` checked disabled`) // boolean attr w/ false should be ignored
})
test('ignore falsy values', () => {
expect(
ssrRenderAttrs({
foo: false,
title: null,
baz: undefined
})
).toBe(` foo="false"`) // non boolean should render `false` as is
})
test('ignore non-renderable values', () => {
expect(
ssrRenderAttrs({
foo: {},
bar: [],
baz: () => {}
})
).toBe(``)
})
test('props to attrs', () => {
expect(
ssrRenderAttrs({
readOnly: true, // simple lower case conversion
htmlFor: 'foobar' // special cases
})
).toBe(` readonly for="foobar"`)
})
test('preserve name on custom element', () => {
expect(
ssrRenderAttrs(
{
fooBar: 'ok'
},
'my-el'
)
).toBe(` fooBar="ok"`)
})
})
describe('ssr: renderAttr', () => {
test('basic', () => {
expect(ssrRenderAttr('foo', 'bar')).toBe(` foo="bar"`)
})
test('null and undefined', () => {
expect(ssrRenderAttr('foo', null)).toBe(``)
expect(ssrRenderAttr('foo', undefined)).toBe(``)
})
test('escape', () => {
expect(ssrRenderAttr('foo', '<script>')).toBe(
` foo="${escapeHtml(`<script>`)}"`
)
})
})
describe('ssr: renderClass', () => {
test('via renderProps', () => {
expect(
ssrRenderAttrs({
class: ['foo', 'bar']
})
).toBe(` class="foo bar"`)
})
test('standalone', () => {
expect(ssrRenderClass(`foo`)).toBe(`foo`)
expect(ssrRenderClass([`foo`, `bar`])).toBe(`foo bar`)
expect(ssrRenderClass({ foo: true, bar: false })).toBe(`foo`)
expect(ssrRenderClass([{ foo: true, bar: false }, `baz`])).toBe(`foo baz`)
})
test('escape class values', () => {
expect(ssrRenderClass(`"><script`)).toBe(`&quot;&gt;&lt;script`)
})
})
describe('ssr: renderStyle', () => {
test('via renderProps', () => {
expect(
ssrRenderAttrs({
style: {
color: 'red'
}
})
).toBe(` style="color:red;"`)
})
test('standalone', () => {
expect(ssrRenderStyle(`color:red`)).toBe(`color:red`)
expect(
ssrRenderStyle({
color: `red`
})
).toBe(`color:red;`)
expect(
ssrRenderStyle([
{ color: `red` },
{ fontSize: `15px` } // case conversion
])
).toBe(`color:red;font-size:15px;`)
})
test('number handling', () => {
expect(
ssrRenderStyle({
fontSize: 15, // should be ignored since font-size requires unit
opacity: 0.5
})
).toBe(`opacity:0.5;`)
})
test('escape inline CSS', () => {
expect(ssrRenderStyle(`"><script`)).toBe(`&quot;&gt;&lt;script`)
expect(
ssrRenderStyle({
color: `"><script`
})
).toBe(`color:&quot;&gt;&lt;script;`)
})
})