improve framework wrapper tests and vue component

This commit is contained in:
Rene Haas
2022-11-07 08:17:54 +01:00
parent c07071ed91
commit 0163a8a607
5 changed files with 108 additions and 85 deletions
@@ -240,4 +240,18 @@ describe('OverlayScrollbarsComponent', () => {
expect(onUpdatedInitial).toHaveBeenCalledTimes(3);
expect(onUpdated).toHaveBeenCalledTimes(3);
});
test('destroy', () => {
const ref: RefObject<OverlayScrollbarsComponentRef> = { current: null };
const { unmount } = render(<OverlayScrollbarsComponent ref={ref} />);
const { instance } = ref.current!;
expect(OverlayScrollbars.valid(instance())).toBe(true);
unmount();
expect(instance()).toBeDefined();
expect(OverlayScrollbars.valid(instance())).toBe(false);
});
});
+1 -13
View File
@@ -1,13 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1247.05px" height="1079.989px" viewBox="336.436 0.005 1247.05 1079.989" enable-background="new 336.436 0.005 1247.05 1079.989" xml:space="preserve">
<g transform="matrix(1.3333 0 0 -1.3333 -76.311 313.34)">
<g transform="translate(178.06 235.01)">
<path fill="#41B883" d="M707.163-0.003l-108-187.062l-108,187.062H131.508l467.655-810.012L1066.819-0.003H707.163z"/>
</g>
<g transform="translate(178.06 235.01)">
<path fill="#34495E" d="M707.163-0.003l-108-187.062l-108,187.062H318.57l280.593-485.998L879.757-0.003H707.163z"/>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69" xmlns:v="https://vecta.io/nano"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>

Before

Width:  |  Height:  |  Size: 914 B

After

Width:  |  Height:  |  Size: 308 B

@@ -1,5 +1,5 @@
<script lang="ts">
import { defineComponent, watch, watchPostEffect, ref, shallowRef, toRefs, onUnmounted } from 'vue';
<script setup lang="ts">
import { ref, unref, shallowRef, toRefs, watch, watchPostEffect, onUnmounted } from 'vue';
import { useOverlayScrollbars } from './useOverlayScrollbars';
import type {
OverlayScrollbarsComponentProps,
@@ -9,77 +9,70 @@ import type { PropType } from 'vue';
import type { EventListeners, EventListenerMap } from 'overlayscrollbars';
const emitNames: (keyof EventListenerMap)[] = ['initialized', 'updated', 'destroyed', 'scroll'];
export default defineComponent({
name: 'OverlayScrollbars',
props: {
element: {
type: String as PropType<OverlayScrollbarsComponentProps['element']>,
default: 'div',
},
options: { type: Object as PropType<OverlayScrollbarsComponentProps['options']> },
events: { type: Object as PropType<OverlayScrollbarsComponentProps['events']> },
},
emits: {
initialized: (...args: EventListenerMap['initialized']) => true,
updated: (...args: EventListenerMap['updated']) => true,
destroyed: (...args: EventListenerMap['destroyed']) => true,
scroll: (...args: EventListenerMap['scroll']) => true,
},
setup(props, { expose, emit }) {
const elementRef = shallowRef<HTMLElement | null>(null);
const slotRef = shallowRef<HTMLElement | null>(null);
const combinedEvents = ref<EventListeners>();
const { element, options, events } = toRefs(props);
const [initialize, instance] = useOverlayScrollbars({ options, events: combinedEvents });
const exposed: OverlayScrollbarsComponentRef = {
instance,
element: () => elementRef.value,
};
expose(exposed);
watch(
() => events.value,
(rawCurrEvents) => {
const currEvents = rawCurrEvents || {};
combinedEvents.value = emitNames.reduce<EventListeners>(
<N extends keyof EventListeners>(obj: EventListeners, name: N) => {
const eventListener = currEvents[name];
obj[name] = [
// @ts-ignore
(...args: EventListenerMap[N]) => emit(name, ...args),
...(Array.isArray(eventListener) ? eventListener : [eventListener]).filter(Boolean),
];
return obj;
},
{}
);
},
{ deep: true, immediate: true }
);
watchPostEffect((onCleanup) => {
const { value: elm } = elementRef;
const { value: slotElm } = slotRef;
if (elm && slotElm) {
const osInstance = initialize({
target: elm,
elements: {
viewport: slotElm,
content: slotElm,
},
});
onCleanup(() => osInstance.destroy());
}
});
onUnmounted(() => instance()?.destroy());
return { elementRef, slotRef, element };
const props = defineProps({
element: {
type: String as PropType<OverlayScrollbarsComponentProps['element']>,
default: 'div',
},
options: { type: Object as PropType<OverlayScrollbarsComponentProps['options']> },
events: { type: Object as PropType<OverlayScrollbarsComponentProps['events']> },
});
const emits = defineEmits({
initialized: (...args: EventListenerMap['initialized']) => true,
updated: (...args: EventListenerMap['updated']) => true,
destroyed: (...args: EventListenerMap['destroyed']) => true,
scroll: (...args: EventListenerMap['scroll']) => true,
} as Record<keyof EventListenerMap, any>);
const elementRef = shallowRef<HTMLElement | null>(null);
const slotRef = shallowRef<HTMLElement | null>(null);
const combinedEvents = ref<EventListeners>();
const { element, options, events } = toRefs(props);
const [initialize, instance] = useOverlayScrollbars({ options, events: combinedEvents });
const exposed: OverlayScrollbarsComponentRef = {
instance,
element: () => elementRef.value,
};
defineExpose(exposed);
onUnmounted(() => instance()?.destroy());
watchPostEffect((onCleanup) => {
const { value: elm } = elementRef;
const { value: slotElm } = slotRef;
if (elm && slotElm) {
const osInstance = initialize({
target: elm,
elements: {
viewport: slotElm,
content: slotElm,
},
});
onCleanup(() => osInstance.destroy());
}
});
watch(
() => unref(events),
(rawCurrEvents) => {
const currEvents = rawCurrEvents || {};
combinedEvents.value = emitNames.reduce<EventListeners>(
<N extends keyof EventListeners>(obj: EventListeners, name: N) => {
const eventListener = currEvents[name];
obj[name] = [
// @ts-ignore
(...args: EventListenerMap[N]) => emits(name, ...args),
...(Array.isArray(eventListener) ? eventListener : [eventListener]).filter(Boolean),
];
return obj;
},
{}
);
},
{ deep: true, immediate: true }
);
</script>
<template>
@@ -70,7 +70,11 @@ export const useOverlayScrollbars = (
variables.value.events = events;
if (OverlayScrollbars.valid(instance)) {
instance.on(events || {}, true);
instance.on(
/* c8 ignore next */
events || {},
true
);
}
},
{ deep: true, immediate: true }
@@ -255,6 +255,30 @@ describe('OverlayScrollbarsComponent', () => {
expect(onUpdated).toHaveBeenCalledTimes(3);
});
test('destroy', () => {
const osRef = ref();
const { unmount } = render({
setup() {
const componentRef = ref(null);
onMounted(() => {
osRef.value = componentRef.value;
});
return () => <OverlayScrollbarsComponent ref={componentRef} />;
},
});
const { instance } = osRef.value!;
expect(OverlayScrollbars.valid(instance())).toBe(true);
unmount();
expect(instance()).toBeDefined();
expect(OverlayScrollbars.valid(instance())).toBe(false);
});
test('emits', async () => {
const { emitted, unmount, container } = render(OverlayScrollbarsComponent);