debian-mirror-gitlab/spec/frontend/vue_compat_test_setup.js
2023-07-09 08:55:56 +05:30

142 lines
4.4 KiB
JavaScript

/* eslint-disable import/no-commonjs */
const Vue = require('vue');
const VTU = require('@vue/test-utils');
const { installCompat: installVTUCompat, fullCompatConfig } = require('vue-test-utils-compat');
function getComponentName(component) {
if (!component) {
return undefined;
}
return (
component.name ||
getComponentName(component.extends) ||
component.mixins?.find((mixin) => getComponentName(mixin))
);
}
function isLegacyExtendedComponent(component) {
return Reflect.has(component, 'super') && component.super.extend({}).super === component.super;
}
function unwrapLegacyVueExtendComponent(selector) {
return isLegacyExtendedComponent(selector) ? selector.options : selector;
}
if (global.document) {
const compatConfig = {
MODE: 2,
GLOBAL_MOUNT: 'suppress-warning',
GLOBAL_EXTEND: 'suppress-warning',
GLOBAL_PROTOTYPE: 'suppress-warning',
RENDER_FUNCTION: 'suppress-warning',
INSTANCE_DESTROY: 'suppress-warning',
INSTANCE_DELETE: 'suppress-warning',
INSTANCE_ATTRS_CLASS_STYLE: 'suppress-warning',
INSTANCE_CHILDREN: 'suppress-warning',
INSTANCE_SCOPED_SLOTS: 'suppress-warning',
INSTANCE_LISTENERS: 'suppress-warning',
INSTANCE_EVENT_EMITTER: 'suppress-warning',
INSTANCE_EVENT_HOOKS: 'suppress-warning',
INSTANCE_SET: 'suppress-warning',
GLOBAL_OBSERVABLE: 'suppress-warning',
GLOBAL_SET: 'suppress-warning',
COMPONENT_FUNCTIONAL: 'suppress-warning',
COMPONENT_V_MODEL: 'suppress-warning',
COMPONENT_ASYNC: 'suppress-warning',
CUSTOM_DIR: 'suppress-warning',
OPTIONS_BEFORE_DESTROY: 'suppress-warning',
OPTIONS_DATA_MERGE: 'suppress-warning',
OPTIONS_DATA_FN: 'suppress-warning',
OPTIONS_DESTROYED: 'suppress-warning',
ATTR_FALSE_VALUE: 'suppress-warning',
COMPILER_V_ON_NATIVE: 'suppress-warning',
COMPILER_V_BIND_OBJECT_ORDER: 'suppress-warning',
CONFIG_WHITESPACE: 'suppress-warning',
CONFIG_OPTION_MERGE_STRATS: 'suppress-warning',
PRIVATE_APIS: 'suppress-warning',
WATCH_ARRAY: 'suppress-warning',
};
let compatH;
Vue.config.compilerOptions.whitespace = 'preserve';
Vue.createApp({
compatConfig: {
MODE: 3,
RENDER_FUNCTION: 'suppress-warning',
},
render(h) {
compatH = h;
},
}).mount(document.createElement('div'));
Vue.configureCompat(compatConfig);
installVTUCompat(VTU, fullCompatConfig, compatH);
VTU.config.global.renderStubDefaultSlot = true;
const noop = () => {};
VTU.config.plugins.createStubs = ({ name, component: rawComponent, registerStub }) => {
const component = unwrapLegacyVueExtendComponent(rawComponent);
const hyphenatedName = name.replace(/\B([A-Z])/g, '-$1').toLowerCase();
const stub = Vue.defineComponent({
name: getComponentName(component),
props: component.props,
model: component.model,
methods: Object.fromEntries(
Object.entries(component.methods ?? {}).map(([key]) => [key, noop]),
),
render() {
const {
$slots: slots = {},
$scopedSlots: scopedSlots = {},
$parent: parent,
$vnode: vnode,
} = this;
const hasStaticDefaultSlot = 'default' in slots && !('default' in scopedSlots);
const isTheOnlyChild = parent?.$.subTree === vnode;
// this condition should be altered when https://github.com/vuejs/vue-test-utils/pull/2068 is merged
// and our codebase will be updated to include it (@vue/test-utils@1.3.6 I assume)
const shouldRenderAllSlots = !hasStaticDefaultSlot && isTheOnlyChild;
const renderSlotByName = (slotName) => {
const slot = scopedSlots[slotName] || slots[slotName];
let result;
if (typeof slot === 'function') {
try {
result = slot({});
} catch {
// intentionally blank
}
} else {
result = slot;
}
return result;
};
const slotContents = shouldRenderAllSlots
? [...new Set([...Object.keys(slots), ...Object.keys(scopedSlots)])]
.map(renderSlotByName)
.filter(Boolean)
: renderSlotByName('default');
return Vue.h(`${hyphenatedName || 'anonymous'}-stub`, this.$props, slotContents);
},
});
if (typeof component === 'function') {
component()?.then?.((resolvedComponent) => {
registerStub({ source: resolvedComponent.default, stub });
});
}
return stub;
};
}