|
|
import {
|
|
|
RPA_REQUIRED_SELECTOR_ENV_KEYS,
|
|
|
RPA_SELECTOR_ENV_KEYS,
|
|
|
} from "@/lib/rpa/env";
|
|
|
import { getSelectorSpecs } from "@/lib/rpa/selector-specs";
|
|
|
import { RpaError } from "@/modules/rpa/errors";
|
|
|
|
|
|
export type RpaSelectorKey = (typeof RPA_SELECTOR_ENV_KEYS)[number];
|
|
|
export type RpaRequiredSelectorKey =
|
|
|
(typeof RPA_REQUIRED_SELECTOR_ENV_KEYS)[number];
|
|
|
|
|
|
/** CI/单测 mock 用占位 selector */
|
|
|
const MOCK_SELECTOR_VALUES: Record<RpaSelectorKey, string> = {
|
|
|
RPA_SELECTOR_PICKUP_STREET: '[data-testid="pickup-street"]',
|
|
|
RPA_SELECTOR_DELIVERY_STREET: '[data-testid="delivery-street"]',
|
|
|
RPA_SELECTOR_ADDRESS_SUGGESTION: ".address-suggestion-item",
|
|
|
RPA_SELECTOR_SUBMIT: 'button[type="submit"]',
|
|
|
RPA_SELECTOR_STANDARD_TAB: '[data-testid="service-standard"]',
|
|
|
RPA_SELECTOR_GUARANTEED_TAB: '[data-testid="service-guaranteed"]',
|
|
|
RPA_SELECTOR_LOWEST_OPTION: '[data-testid="rate-lowest"]',
|
|
|
RPA_SELECTOR_FASTEST_OPTION: '[data-testid="rate-fastest"]',
|
|
|
RPA_SELECTOR_PRICE: '[data-testid="rate-price"]',
|
|
|
RPA_SELECTOR_QUOTE_WIDGET: "#react-quoter-landing-plugin",
|
|
|
};
|
|
|
|
|
|
export function isRpaMockMode(): boolean {
|
|
|
return process.env.RPA_MOCK_MODE === "true";
|
|
|
}
|
|
|
|
|
|
/** 非空 selector;禁止空字符串 fallback(env 显式空串时走内置回退,仍空则 fail-fast) */
|
|
|
export function getSelector(key: RpaSelectorKey): string {
|
|
|
const spec = getSelectorSpecs(key).find((s) => s.trim().length > 0)?.trim();
|
|
|
if (spec) {
|
|
|
return spec;
|
|
|
}
|
|
|
if (isRpaMockMode()) {
|
|
|
const mock = MOCK_SELECTOR_VALUES[key]?.trim();
|
|
|
if (mock) {
|
|
|
return mock;
|
|
|
}
|
|
|
}
|
|
|
throw new RpaError("STRUCT_CHANGE", `${key} 未配置或为空`, {
|
|
|
retryable: false,
|
|
|
});
|
|
|
}
|
|
|
|
|
|
/** @deprecated 使用 getSelector */
|
|
|
export function getRpaSelector(key: RpaSelectorKey): string {
|
|
|
return getSelector(key);
|
|
|
}
|
|
|
|
|
|
/** rpa-worker 启动前校验 registry:任一必填 key 无法解析为非空 selector 则 fail-fast */
|
|
|
export function assertRpaSelectorsEnv(): void {
|
|
|
if (isRpaMockMode()) {
|
|
|
return;
|
|
|
}
|
|
|
const failures: string[] = [];
|
|
|
for (const key of RPA_REQUIRED_SELECTOR_ENV_KEYS) {
|
|
|
try {
|
|
|
getSelector(key);
|
|
|
} catch {
|
|
|
failures.push(key);
|
|
|
}
|
|
|
}
|
|
|
if (failures.length > 0) {
|
|
|
throw new Error(
|
|
|
`[rpa-worker] RPA selector 未初始化或为空: ${failures.join(", ")}`,
|
|
|
);
|
|
|
}
|
|
|
}
|