miniprogram-simulate
Version:
tools for miniprogram custom component unit test
215 lines (201 loc) • 5.3 kB
JavaScript
/**
* 参考实现 https://github.com/facebook/jest/blob/3f107a3377/packages/pretty-format/src/plugins/ReactTestComponent.ts
*/
// eslint-disable-next-line import/no-extraneous-dependencies
const _markup = require('pretty-format/build/plugins/lib/markup')
/**
* 用于识别 j-component toJSON 函数生成的 JSON 对象
*/
const testSymbol =
typeof Symbol === 'function' && Symbol.for
? Symbol.for('j-component.json')
: 0xd846fe
/**
* @typedef {object} JComponentJSON j-component toJSON 函数生成的 JSON 对象
* @prop {string} tagName
* @prop {{ name: string; value: any }[]} attrs
* @prop {{ [event: string]: { handler: string; isCapture: boolean; isMutated: boolean; isCatch: boolean; name: string } }} event
* @prop {JComponentJSON[]} children
*/
/**
* @typedef {import('pretty-format/build/types').NewPlugin} NewPlugin
* @typedef {import('pretty-format/build/types').Config} Config
* @typedef {import('pretty-format/build/types').Printer} Printer
* @typedef {import('pretty-format/build/types').Refs} Refs
*/
/**
* 暴露给 pretty-format 的检测函数
* 仅有检测返回 true 的对象才会传入 serialize
* @param {any} val
*/
const test = function test(val) {
return val && val.$$typeof === testSymbol
}
/**
* 打印节点属性
* @param {JComponentJSON['attrs']} attrs
* @param {Config} config
* @param {string} indentation
* @param {number} depth
* @param {Refs} refs
* @param {Printer} printer
*/
const printAttrs = function printAttrs(
attrs,
config,
indentation,
depth,
refs,
printer
) {
const indentationNext = indentation + config.indent
const colors = config.colors
return Array.from(attrs)
.sort(function(a, b) {
return a.name.localeCompare(b.name)
})
.map(function(attr) {
const name = attr.name
const value = attr.value
let printed = printer(value, config, indentationNext, depth, refs)
if (typeof value !== 'string') {
if (printed.indexOf('\n') !== -1) {
printed =
config.spacingOuter +
indentationNext +
printed +
config.spacingOuter +
indentation
}
printed = '"{{' + printed + '}}"'
}
return (
config.spacingInner +
indentation +
colors.prop.open +
name +
colors.prop.close +
'=' +
colors.value.open +
printed +
colors.value.close
)
})
.join('')
}
/**
* 打印节点事件绑定
* @param {JComponentJSON['event']} event
* @param {Config} config
* @param {string} indentation
* @param {number} depth
* @param {Refs} refs
* @param {Printer} printer
*/
const printEvent = function printEvent(
event,
config,
indentation,
depth,
refs,
printer
) {
const indentationNext = indentation + config.indent
const colors = config.colors
return Object.keys(event)
.sort()
.map(function(eventName) {
const eventInfo = event[eventName]
const handler = eventInfo.handler
const isCapture = eventInfo.isCapture
const isMutated = eventInfo.isMutated
const isCatch = eventInfo.isCatch
const attrName =
(isCapture ? 'capture-' : '') +
(isMutated ? 'mut-' : '') +
(isCatch ? 'catch' : 'bind') +
':' +
eventName
const printed = printer(handler, config, indentationNext, depth, refs)
return (
config.spacingInner +
indentation +
colors.prop.open +
attrName +
colors.prop.close +
'=' +
colors.value.open +
printed +
colors.value.close
)
})
.join('')
}
/**
* 打印节点所有属性
* @param {JComponentJSON} object
* @param {Config} config
* @param {string} indentation
* @param {number} depth
* @param {Refs} refs
* @param {Printer} printer
*/
const printProps = function printProps(
object,
config,
indentation,
depth,
refs,
printer
) {
return (
printAttrs(object.attrs, config, indentation, depth, refs, printer) +
printEvent(object.event, config, indentation, depth, refs, printer)
)
}
/**
* 暴露给 pretty-format 的打印函数
* 仅有通过 test 函数检测返回 true 的对象才会传入 serialize
* @param {JComponentJSON} object
* @param {Config} config
* @param {string} indentation
* @param {number} depth
* @param {Refs} refs
* @param {Printer} printer
*/
const serialize = function serialize(
object,
config,
indentation,
depth,
refs,
printer
) {
return ++depth > config.maxDepth
? _markup.printElementAsLeaf(object.tagName, config)
: _markup.printElement(
object.tagName,
printProps(
object,
config,
indentation + config.indent,
depth,
refs,
printer
),
_markup.printChildren(
object.children,
config,
indentation + config.indent,
depth,
refs,
printer
),
config,
indentation
)
}
module.exports = {
serialize,
test,
}