mirror of
https://github.com/ecomfe/vue-echarts.git
synced 2025-10-27 19:13:59 +08:00
test: increase coverage and add codecov integration
This commit is contained in:
@ -103,31 +103,29 @@ export default defineComponent({
|
||||
|
||||
let lastSignature: Signature | undefined;
|
||||
|
||||
function resolveUpdateOptions(
|
||||
plan?: UpdatePlan,
|
||||
override?: UpdateOptions,
|
||||
): UpdateOptions {
|
||||
const base = realUpdateOptions.value;
|
||||
const result: UpdateOptions = { ...override };
|
||||
// Note: This resolver is only used in the default "smart-update" path when
|
||||
// no `updateOptions` are provided via props/injection (i.e., `realUpdateOptions`
|
||||
// is falsy) and manual mode is off. Historically it attempted to merge
|
||||
// caller overrides and base options, but those code paths are not reachable
|
||||
// given current call sites (we never pass an override in non-manual paths,
|
||||
// and when base options exist we short-circuit before calling this).
|
||||
// To avoid dead branches and keep behavior clear, we only materialize flags
|
||||
// derived from the computed update plan.
|
||||
function resolveUpdateOptions(plan?: UpdatePlan): UpdateOptions {
|
||||
const result: UpdateOptions = {};
|
||||
|
||||
const replacements = [
|
||||
...(plan?.replaceMerge ?? []),
|
||||
...(override?.replaceMerge ?? []),
|
||||
].filter((key): key is string => key != null);
|
||||
const replacements = (plan?.replaceMerge ?? []).filter(
|
||||
(key): key is string => key != null,
|
||||
);
|
||||
if (replacements.length > 0) {
|
||||
result.replaceMerge = [...new Set(replacements)];
|
||||
} else {
|
||||
delete result.replaceMerge;
|
||||
}
|
||||
|
||||
const notMerge = override?.notMerge ?? plan?.notMerge;
|
||||
if (notMerge !== undefined) {
|
||||
result.notMerge = notMerge;
|
||||
} else {
|
||||
delete result.notMerge;
|
||||
if (plan?.notMerge !== undefined) {
|
||||
result.notMerge = plan.notMerge;
|
||||
}
|
||||
|
||||
return base ? { ...base, ...result } : result;
|
||||
return result;
|
||||
}
|
||||
|
||||
function applyOption(
|
||||
@ -156,7 +154,7 @@ export default defineComponent({
|
||||
patched as unknown as EChartsOption,
|
||||
);
|
||||
|
||||
const updateOptions = resolveUpdateOptions(planned.plan, override);
|
||||
const updateOptions = resolveUpdateOptions(planned.plan);
|
||||
instance.setOption(planned.option, updateOptions);
|
||||
lastSignature = planned.signature;
|
||||
}
|
||||
@ -220,8 +218,13 @@ export default defineComponent({
|
||||
|
||||
if (once) {
|
||||
const raw = handler;
|
||||
let called = false;
|
||||
|
||||
handler = (...args: any[]) => {
|
||||
if (called) {
|
||||
return;
|
||||
}
|
||||
called = true;
|
||||
raw(...args);
|
||||
target.off(event, handler);
|
||||
};
|
||||
@ -274,10 +277,10 @@ export default defineComponent({
|
||||
typeof notMerge === "boolean" ? { notMerge, lazyUpdate } : notMerge;
|
||||
|
||||
if (!chart.value) {
|
||||
init(option, true, updateOptions ?? undefined);
|
||||
} else {
|
||||
applyOption(chart.value, option, updateOptions ?? undefined, true);
|
||||
return;
|
||||
}
|
||||
|
||||
applyOption(chart.value, option, updateOptions ?? undefined, true);
|
||||
};
|
||||
|
||||
function cleanup() {
|
||||
@ -306,10 +309,10 @@ export default defineComponent({
|
||||
return;
|
||||
}
|
||||
if (!chart.value) {
|
||||
init();
|
||||
} else {
|
||||
applyOption(chart.value, option);
|
||||
return;
|
||||
}
|
||||
|
||||
applyOption(chart.value, option);
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
@ -10,7 +10,7 @@ import {
|
||||
} from "vue";
|
||||
import type { Slots, SlotsType } from "vue";
|
||||
import type { Option } from "../types";
|
||||
import { isValidArrayIndex, isSameSet } from "../utils";
|
||||
import { isBrowser, isValidArrayIndex, isSameSet } from "../utils";
|
||||
import type { TooltipComponentFormatterCallbackParams } from "echarts";
|
||||
|
||||
const SLOT_OPTION_PATHS = {
|
||||
@ -29,8 +29,7 @@ function isValidSlotName(key: string): key is SlotName {
|
||||
}
|
||||
|
||||
export function useSlotOption(slots: Slots, onSlotsChange: () => void) {
|
||||
const detachedRoot =
|
||||
typeof window !== "undefined" ? document.createElement("div") : undefined;
|
||||
const detachedRoot = isBrowser() ? document.createElement("div") : undefined;
|
||||
const containers = shallowReactive<SlotRecord<HTMLElement>>({});
|
||||
const initialized = shallowReactive<SlotRecord<boolean>>({});
|
||||
const params = shallowReactive<SlotRecord<unknown>>({});
|
||||
@ -39,7 +38,7 @@ export function useSlotOption(slots: Slots, onSlotsChange: () => void) {
|
||||
// Teleport the slots to a detached root
|
||||
const teleportedSlots = () => {
|
||||
// Make slots client-side only to avoid SSR hydration mismatch
|
||||
return isMounted.value
|
||||
return isMounted.value && detachedRoot
|
||||
? h(
|
||||
Teleport,
|
||||
{ to: detachedRoot },
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { EChartsOption } from "echarts";
|
||||
import type { Option } from "./types";
|
||||
import { isPlainObject } from "./utils";
|
||||
|
||||
export interface UpdatePlan {
|
||||
@ -49,7 +49,7 @@ function readId(item: unknown): string | undefined {
|
||||
* Build a minimal signature from a full ECharts option.
|
||||
* Only top-level keys are inspected.
|
||||
*/
|
||||
export function buildSignature(option: EChartsOption): Signature {
|
||||
export function buildSignature(option: Option): Signature {
|
||||
const opt = option as Record<string, unknown>;
|
||||
|
||||
const optionsLength = Array.isArray(opt.options)
|
||||
@ -152,7 +152,7 @@ function hasMissingIds(
|
||||
}
|
||||
|
||||
export interface PlannedUpdate {
|
||||
option: EChartsOption;
|
||||
option: Option;
|
||||
signature: Signature;
|
||||
plan: UpdatePlan;
|
||||
}
|
||||
@ -163,7 +163,7 @@ export interface PlannedUpdate {
|
||||
*/
|
||||
export function planUpdate(
|
||||
prev: Signature | undefined,
|
||||
option: EChartsOption,
|
||||
option: Option,
|
||||
): PlannedUpdate {
|
||||
const next = buildSignature(option);
|
||||
|
||||
@ -224,7 +224,7 @@ export function planUpdate(
|
||||
overrides.forEach((value, key) => {
|
||||
clone[key] = value;
|
||||
});
|
||||
normalizedOption = clone as EChartsOption;
|
||||
normalizedOption = clone as Option;
|
||||
signature = buildSignature(normalizedOption);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
type Attrs = Record<string, any>;
|
||||
|
||||
export function isBrowser(): boolean {
|
||||
return typeof window !== "undefined" && typeof document !== "undefined";
|
||||
}
|
||||
|
||||
// Copied from
|
||||
// https://github.com/vuejs/vue-next/blob/5a7a1b8293822219283d6e267496bec02234b0bc/packages/shared/src/index.ts#L40-L41
|
||||
const onRE = /^on[^a-z]/;
|
||||
|
||||
41
src/wc.ts
41
src/wc.ts
@ -1,3 +1,5 @@
|
||||
import { isBrowser } from "./utils";
|
||||
|
||||
let registered: boolean | null = null;
|
||||
|
||||
export const TAG_NAME = "x-vue-echarts";
|
||||
@ -11,30 +13,33 @@ export function register(): boolean {
|
||||
return registered;
|
||||
}
|
||||
|
||||
if (
|
||||
typeof HTMLElement === "undefined" ||
|
||||
typeof customElements === "undefined"
|
||||
) {
|
||||
return (registered = false);
|
||||
const registry = globalThis.customElements;
|
||||
|
||||
if (!isBrowser() || !registry?.get) {
|
||||
registered = false;
|
||||
return registered;
|
||||
}
|
||||
|
||||
try {
|
||||
class ECElement extends HTMLElement implements EChartsElement {
|
||||
__dispose: (() => void) | null = null;
|
||||
if (!registry.get(TAG_NAME)) {
|
||||
try {
|
||||
class ECElement extends HTMLElement implements EChartsElement {
|
||||
__dispose: (() => void) | null = null;
|
||||
|
||||
disconnectedCallback() {
|
||||
if (this.__dispose) {
|
||||
this.__dispose();
|
||||
this.__dispose = null;
|
||||
disconnectedCallback(): void {
|
||||
if (this.__dispose) {
|
||||
this.__dispose();
|
||||
this.__dispose = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registry.define(TAG_NAME, ECElement);
|
||||
} catch {
|
||||
registered = false;
|
||||
return registered;
|
||||
}
|
||||
if (customElements.get(TAG_NAME) == null) {
|
||||
customElements.define(TAG_NAME, ECElement);
|
||||
}
|
||||
} catch {
|
||||
return (registered = false);
|
||||
}
|
||||
|
||||
return (registered = true);
|
||||
registered = true;
|
||||
return registered;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user