vite-plugin-vue-testid 1.0.9 → 1.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/runtime.d.ts +13 -2
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +284 -334
- package/package.json +2 -2
package/dist/runtime.d.ts
CHANGED
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
*
|
|
9
9
|
* createApp(App).mount('#app')
|
|
10
10
|
* setupAntTestIds()
|
|
11
|
+
*
|
|
12
|
+
* // 支持自定义 prefixCls(对应 ant-design-vue ConfigProvider 的 prefixCls):
|
|
13
|
+
* setupAntTestIds({ prefixCls: 'custom' })
|
|
11
14
|
* ```
|
|
12
15
|
*/
|
|
13
16
|
export interface RuntimeOptions {
|
|
@@ -16,6 +19,11 @@ export interface RuntimeOptions {
|
|
|
16
19
|
* @default 'data-testid'
|
|
17
20
|
*/
|
|
18
21
|
attributeName?: string;
|
|
22
|
+
/**
|
|
23
|
+
* ant-design-vue CSS 类名前缀,对应 ConfigProvider 的 prefixCls
|
|
24
|
+
* @default 'ant'
|
|
25
|
+
*/
|
|
26
|
+
prefixCls?: string;
|
|
19
27
|
/**
|
|
20
28
|
* 自定义组件 CSS 选择器 → testid 前缀映射。
|
|
21
29
|
* 会与默认映射合并(自定义覆盖默认)。
|
|
@@ -56,7 +64,8 @@ export type PanelInjectStrategy = (ctx: PanelContext) => void;
|
|
|
56
64
|
* - 所有 ant-design-vue 组件根元素(input / select / button / picker / ...)
|
|
57
65
|
* - teleport 弹出层面板(日期选择器 / 级联选择器 / 下拉选择器)
|
|
58
66
|
* - Menu 子元素(inheritAttrs:false 兜底)
|
|
59
|
-
* -
|
|
67
|
+
* - InputNumber 内部输入框及增减按钮
|
|
68
|
+
* - Slider handle、Rate 星星、Upload 内部 file input
|
|
60
69
|
*
|
|
61
70
|
* @returns 清理函数,调用后停止监听
|
|
62
71
|
*
|
|
@@ -67,12 +76,14 @@ export type PanelInjectStrategy = (ctx: PanelContext) => void;
|
|
|
67
76
|
*
|
|
68
77
|
* createApp(App).mount('#app')
|
|
69
78
|
* setupAntTestIds()
|
|
79
|
+
*
|
|
80
|
+
* // 配合 ConfigProvider 自定义 prefixCls:
|
|
81
|
+
* setupAntTestIds({ prefixCls: 'custom' })
|
|
70
82
|
* ```
|
|
71
83
|
*/
|
|
72
84
|
export declare function setupAntTestIds(opts?: RuntimeOptions): () => void;
|
|
73
85
|
/**
|
|
74
86
|
* @deprecated 使用 {@link setupAntTestIds} 替代。
|
|
75
|
-
* 保留此别名以兼容现有代码。
|
|
76
87
|
*/
|
|
77
88
|
export declare const setupAntDropdownTestIds: typeof setupAntTestIds;
|
|
78
89
|
/**
|
package/dist/runtime.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEnC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,GAAG,SAAS,CAAC,CAAA;CACzD;AAED,MAAM,WAAW,YAAY;IAC3B,kBAAkB;IAClB,SAAS,EAAE,WAAW,CAAA;IACtB,iBAAiB;IACjB,OAAO,EAAE,WAAW,GAAG,IAAI,CAAA;IAC3B,oBAAoB;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB;IACjB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,YAAY,KAAK,IAAI,CAAA;AAsjB7D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,eAAe,CAAC,IAAI,GAAE,cAAmB,GAAG,MAAM,IAAI,CA6ErE;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB,wBAAkB,CAAA;AAMtD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,GAAE,cAAmB,GAAG,IAAI,CAgCtE"}
|
package/dist/runtime.js
CHANGED
|
@@ -1,60 +1,65 @@
|
|
|
1
1
|
// src/runtime.ts
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
2
|
+
var sel = (pc, name) => `.${pc}-${name}`;
|
|
3
|
+
var cls = (pc, name) => `${pc}-${name}`;
|
|
4
|
+
function buildComponentMatchers(pc) {
|
|
5
|
+
return [
|
|
6
|
+
// ── 输入框变体(按 specificity 降序)──
|
|
7
|
+
{ selector: sel(pc, "input-search"), prefix: "a-input-search" },
|
|
8
|
+
{ selector: sel(pc, "input-affix-wrapper"), prefix: "a-input" },
|
|
9
|
+
{ selector: sel(pc, "input-textarea"), prefix: "a-textarea" },
|
|
10
|
+
{ selector: sel(pc, "input-number"), prefix: "a-input-number" },
|
|
11
|
+
// ── 选择器 ──
|
|
12
|
+
{ selector: sel(pc, "select"), prefix: "a-select", withId: true },
|
|
13
|
+
{ selector: sel(pc, "cascader"), prefix: "a-cascader", withId: true },
|
|
14
|
+
{ selector: sel(pc, "tree-select"), prefix: "a-tree-select" },
|
|
15
|
+
// ── 日期/时间 ──
|
|
16
|
+
{ selector: sel(pc, "picker"), prefix: "a-date-picker", withId: true },
|
|
17
|
+
// ── 表单组件 ──
|
|
18
|
+
{ selector: sel(pc, "radio-group"), prefix: "a-radio-group" },
|
|
19
|
+
{ selector: sel(pc, "radio-wrapper"), prefix: "a-radio" },
|
|
20
|
+
{ selector: sel(pc, "checkbox-group"), prefix: "a-checkbox-group" },
|
|
21
|
+
{ selector: sel(pc, "checkbox-wrapper"), prefix: "a-checkbox" },
|
|
22
|
+
{ selector: sel(pc, "switch"), prefix: "a-switch" },
|
|
23
|
+
{ selector: sel(pc, "slider"), prefix: "a-slider" },
|
|
24
|
+
{ selector: sel(pc, "rate"), prefix: "a-rate" },
|
|
25
|
+
{ selector: sel(pc, "form-item"), prefix: "a-form-item" },
|
|
26
|
+
// ── 按钮 & 上传 ──
|
|
27
|
+
{ selector: sel(pc, "btn"), prefix: "a-button" },
|
|
28
|
+
{ selector: sel(pc, "upload"), prefix: "a-upload", withId: true },
|
|
29
|
+
// ── 弹窗 ──
|
|
30
|
+
{ selector: sel(pc, "modal-wrap"), prefix: "a-modal", withId: true },
|
|
31
|
+
// ── 菜单 ──
|
|
32
|
+
{ selector: sel(pc, "menu"), prefix: "a-menu" },
|
|
33
|
+
// ── 纯 input / textarea(必须排在最后)──
|
|
34
|
+
{ selector: `input.${cls(pc, "input")}`, prefix: "a-input" },
|
|
35
|
+
{ selector: `textarea.${cls(pc, "input")}`, prefix: "a-textarea" }
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
function buildSkipSelectors(pc) {
|
|
39
|
+
return [
|
|
40
|
+
sel(pc, "input-affix-wrapper"),
|
|
41
|
+
sel(pc, "input-textarea"),
|
|
42
|
+
sel(pc, "input-search"),
|
|
43
|
+
sel(pc, "input-number"),
|
|
44
|
+
sel(pc, "picker"),
|
|
45
|
+
sel(pc, "select"),
|
|
46
|
+
sel(pc, "cascader")
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
function isInnerInput(el, skipSelectors) {
|
|
45
50
|
if (el.tagName !== "INPUT" && el.tagName !== "TEXTAREA") return false;
|
|
46
|
-
for (const
|
|
47
|
-
if (el.closest(
|
|
51
|
+
for (const s of skipSelectors) {
|
|
52
|
+
if (el.closest(s)) return true;
|
|
48
53
|
}
|
|
49
54
|
return false;
|
|
50
55
|
}
|
|
51
|
-
function injectComponentRoots(root, matchers, attrName, counter) {
|
|
56
|
+
function injectComponentRoots(root, matchers, attrName, counter, skipSelectors) {
|
|
52
57
|
for (const { selector, prefix, withId } of matchers) {
|
|
53
58
|
const candidates = root.matches(selector) ? [root] : Array.from(root.querySelectorAll(selector));
|
|
54
59
|
for (const el of candidates) {
|
|
55
60
|
if (!(el instanceof HTMLElement)) continue;
|
|
56
61
|
if (el.hasAttribute(attrName)) continue;
|
|
57
|
-
if (isInnerInput(el)) continue;
|
|
62
|
+
if (isInnerInput(el, skipSelectors)) continue;
|
|
58
63
|
const testId = `${prefix}-${counter.value++}`;
|
|
59
64
|
el.setAttribute(attrName, testId);
|
|
60
65
|
if (withId && !el.hasAttribute("id")) {
|
|
@@ -63,12 +68,6 @@ function injectComponentRoots(root, matchers, attrName, counter) {
|
|
|
63
68
|
}
|
|
64
69
|
}
|
|
65
70
|
}
|
|
66
|
-
function getPanelMode(panel) {
|
|
67
|
-
if (panel.classList.contains("ant-picker-month-panel")) return "month";
|
|
68
|
-
if (panel.classList.contains("ant-picker-year-panel")) return "year";
|
|
69
|
-
if (panel.classList.contains("ant-picker-decade-panel")) return "decade";
|
|
70
|
-
return "date";
|
|
71
|
-
}
|
|
72
71
|
var MONTH_NAMES = [
|
|
73
72
|
"jan",
|
|
74
73
|
"feb",
|
|
@@ -83,8 +82,14 @@ var MONTH_NAMES = [
|
|
|
83
82
|
"nov",
|
|
84
83
|
"dec"
|
|
85
84
|
];
|
|
86
|
-
function
|
|
87
|
-
|
|
85
|
+
function getPanelMode(panel, pc) {
|
|
86
|
+
if (panel.classList.contains(cls(pc, "picker-month-panel"))) return "month";
|
|
87
|
+
if (panel.classList.contains(cls(pc, "picker-year-panel"))) return "year";
|
|
88
|
+
if (panel.classList.contains(cls(pc, "picker-decade-panel"))) return "decade";
|
|
89
|
+
return "date";
|
|
90
|
+
}
|
|
91
|
+
function injectHeaderViewButtons(panel, prefix, attrName, suffix, pc) {
|
|
92
|
+
const headerView = panel.querySelector(sel(pc, "picker-header-view"));
|
|
88
93
|
if (!headerView) return;
|
|
89
94
|
const buttons = headerView.querySelectorAll("button");
|
|
90
95
|
buttons.forEach((btn) => {
|
|
@@ -106,18 +111,16 @@ function injectHeaderViewButtons(panel, prefix, attrName, suffix) {
|
|
|
106
111
|
el.setAttribute(attrName, `${prefix}-${name}${suffix}`);
|
|
107
112
|
});
|
|
108
113
|
}
|
|
109
|
-
function injectPanelCells(panel, prefix, attrName, suffix) {
|
|
110
|
-
const mode = getPanelMode(panel);
|
|
111
|
-
const cells = panel.querySelectorAll("
|
|
114
|
+
function injectPanelCells(panel, prefix, attrName, suffix, pc) {
|
|
115
|
+
const mode = getPanelMode(panel, pc);
|
|
116
|
+
const cells = panel.querySelectorAll(sel(pc, "picker-cell-inner"));
|
|
112
117
|
cells.forEach((cell) => {
|
|
113
118
|
const el = cell;
|
|
114
119
|
if (el.hasAttribute(attrName)) return;
|
|
115
120
|
const raw = (el.getAttribute("title") || el.textContent?.trim() || "").replace(/\s+/g, "-");
|
|
116
|
-
let label;
|
|
117
121
|
switch (mode) {
|
|
118
122
|
case "month":
|
|
119
|
-
|
|
120
|
-
el.setAttribute(attrName, `${prefix}-month-${label}${suffix}`);
|
|
123
|
+
el.setAttribute(attrName, `${prefix}-month-${raw.length >= 2 ? raw.slice(-2) : raw}${suffix}`);
|
|
121
124
|
break;
|
|
122
125
|
case "year":
|
|
123
126
|
el.setAttribute(attrName, `${prefix}-year-${raw}${suffix}`);
|
|
@@ -131,145 +134,159 @@ function injectPanelCells(panel, prefix, attrName, suffix) {
|
|
|
131
134
|
}
|
|
132
135
|
});
|
|
133
136
|
}
|
|
134
|
-
function injectSinglePanel(panel, prefix, attrName, suffix) {
|
|
135
|
-
const mode = getPanelMode(panel);
|
|
137
|
+
function injectSinglePanel(panel, prefix, attrName, suffix, pc) {
|
|
138
|
+
const mode = getPanelMode(panel, pc);
|
|
136
139
|
const setAttr = (selector, name) => {
|
|
137
140
|
const el = panel.querySelector(selector);
|
|
138
141
|
if (el && !el.hasAttribute(attrName)) {
|
|
139
142
|
el.setAttribute(attrName, `${prefix}-${name}${suffix}`);
|
|
140
143
|
}
|
|
141
144
|
};
|
|
142
|
-
setAttr("
|
|
143
|
-
setAttr("
|
|
144
|
-
setAttr("
|
|
145
|
-
setAttr("
|
|
146
|
-
setAttr("
|
|
147
|
-
injectHeaderViewButtons(panel, prefix, attrName, suffix);
|
|
148
|
-
injectPanelCells(panel, prefix, attrName, suffix);
|
|
145
|
+
setAttr(sel(pc, "picker-header-super-prev-btn"), "super-prev");
|
|
146
|
+
setAttr(sel(pc, "picker-header-prev-btn"), "prev");
|
|
147
|
+
setAttr(sel(pc, "picker-header-next-btn"), "next");
|
|
148
|
+
setAttr(sel(pc, "picker-header-super-next-btn"), "super-next");
|
|
149
|
+
setAttr(sel(pc, "picker-header-view"), `header-${mode}`);
|
|
150
|
+
injectHeaderViewButtons(panel, prefix, attrName, suffix, pc);
|
|
151
|
+
injectPanelCells(panel, prefix, attrName, suffix, pc);
|
|
149
152
|
}
|
|
150
|
-
function
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
153
|
+
function makeInjectPickerPanel(pc) {
|
|
154
|
+
return (ctx) => {
|
|
155
|
+
const { container, triggerTestId, attrName } = ctx;
|
|
156
|
+
const prefix = `${triggerTestId}-dropdown`;
|
|
157
|
+
container.setAttribute(attrName, prefix);
|
|
158
|
+
const isRange = container.classList.contains(cls(pc, "picker-dropdown-range"));
|
|
159
|
+
const injectAllPanels = () => {
|
|
160
|
+
const panels = container.querySelectorAll(sel(pc, "picker-panel"));
|
|
161
|
+
if (isRange && panels.length >= 2) {
|
|
162
|
+
injectSinglePanel(panels[0], prefix, attrName, "-left", pc);
|
|
163
|
+
injectSinglePanel(panels[1], prefix, attrName, "-right", pc);
|
|
164
|
+
} else {
|
|
165
|
+
const panel = panels[0] || container;
|
|
166
|
+
injectSinglePanel(panel, prefix, attrName, "", pc);
|
|
167
|
+
}
|
|
168
|
+
const presets = container.querySelectorAll(`${sel(pc, "picker-presets")} .${cls(pc, "tag")}`);
|
|
169
|
+
presets.forEach((tag) => {
|
|
170
|
+
const el = tag;
|
|
171
|
+
if (el.hasAttribute(attrName)) return;
|
|
172
|
+
const text = el.textContent?.trim() || "";
|
|
173
|
+
el.setAttribute(attrName, `${prefix}-preset-${text}`);
|
|
174
|
+
});
|
|
175
|
+
const timeColumns = container.querySelectorAll(sel(pc, "picker-time-panel-column"));
|
|
176
|
+
timeColumns.forEach((col, i) => {
|
|
177
|
+
const el = col;
|
|
178
|
+
if (el.hasAttribute(attrName)) return;
|
|
179
|
+
el.setAttribute(attrName, `${prefix}-time-column-${i}`);
|
|
180
|
+
const items = col.querySelectorAll("li");
|
|
181
|
+
items.forEach((item) => {
|
|
182
|
+
const li = item;
|
|
183
|
+
if (li.hasAttribute(attrName)) return;
|
|
184
|
+
const text = li.textContent?.trim() || "";
|
|
185
|
+
li.setAttribute(attrName, `${prefix}-time-${i}-${text}`);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
const setFooterBtn = (selector, name) => {
|
|
189
|
+
const btn = container.querySelector(selector);
|
|
190
|
+
if (btn && !btn.hasAttribute(attrName)) {
|
|
191
|
+
btn.setAttribute(attrName, `${prefix}-${name}`);
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
setFooterBtn(`${sel(pc, "picker-ok")} button`, "ok");
|
|
195
|
+
setFooterBtn(`${sel(pc, "picker-now")} button`, "now");
|
|
196
|
+
setFooterBtn(sel(pc, "picker-now-btn"), "now");
|
|
197
|
+
};
|
|
198
|
+
injectAllPanels();
|
|
199
|
+
if (!_observedContainers.has(container)) {
|
|
200
|
+
_observedContainers.add(container);
|
|
201
|
+
let timer = null;
|
|
202
|
+
const observer = new MutationObserver(() => {
|
|
203
|
+
if (timer !== null) clearTimeout(timer);
|
|
204
|
+
timer = setTimeout(() => {
|
|
205
|
+
injectAllPanels();
|
|
206
|
+
}, 50);
|
|
207
|
+
});
|
|
208
|
+
observer.observe(container, { childList: true, subtree: true });
|
|
163
209
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
const el =
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const items = col.querySelectorAll("li");
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
function makeInjectCascaderPanel(pc) {
|
|
213
|
+
return (ctx) => {
|
|
214
|
+
const { container, triggerTestId, attrName } = ctx;
|
|
215
|
+
const prefix = `${triggerTestId}-dropdown`;
|
|
216
|
+
container.setAttribute(attrName, prefix);
|
|
217
|
+
const menus = container.querySelectorAll(sel(pc, "cascader-menu"));
|
|
218
|
+
menus.forEach((menu, i) => {
|
|
219
|
+
const el = menu;
|
|
220
|
+
el.setAttribute(attrName, `${prefix}-menu-${i}`);
|
|
221
|
+
const items = menu.querySelectorAll(sel(pc, "cascader-menu-item"));
|
|
177
222
|
items.forEach((item) => {
|
|
178
223
|
const li = item;
|
|
179
|
-
if (li.hasAttribute(attrName)) return;
|
|
180
224
|
const text = li.textContent?.trim() || "";
|
|
181
|
-
li.setAttribute(attrName, `${prefix}-
|
|
225
|
+
li.setAttribute(attrName, `${prefix}-item-${text}`);
|
|
182
226
|
});
|
|
183
227
|
});
|
|
184
|
-
const setFooterBtn = (selector, name) => {
|
|
185
|
-
const btn = container.querySelector(selector);
|
|
186
|
-
if (btn && !btn.hasAttribute(attrName)) {
|
|
187
|
-
btn.setAttribute(attrName, `${prefix}-${name}`);
|
|
188
|
-
}
|
|
189
|
-
};
|
|
190
|
-
setFooterBtn(".ant-picker-ok button", "ok");
|
|
191
|
-
setFooterBtn(".ant-picker-now button", "now");
|
|
192
|
-
setFooterBtn(".ant-picker-now-btn", "now");
|
|
193
228
|
};
|
|
194
|
-
injectAllPanels();
|
|
195
|
-
if (!_observedContainers.has(container)) {
|
|
196
|
-
_observedContainers.add(container);
|
|
197
|
-
let timer = null;
|
|
198
|
-
const observer = new MutationObserver(() => {
|
|
199
|
-
if (timer !== null) clearTimeout(timer);
|
|
200
|
-
timer = setTimeout(() => {
|
|
201
|
-
injectAllPanels();
|
|
202
|
-
}, 50);
|
|
203
|
-
});
|
|
204
|
-
observer.observe(container, { childList: true, subtree: true });
|
|
205
|
-
}
|
|
206
229
|
}
|
|
207
|
-
function
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
230
|
+
function makeInjectSelectPanel(pc) {
|
|
231
|
+
return (ctx) => {
|
|
232
|
+
const { container, triggerTestId, attrName } = ctx;
|
|
233
|
+
const prefix = `${triggerTestId}-dropdown`;
|
|
234
|
+
container.setAttribute(attrName, prefix);
|
|
235
|
+
const injectAllItems = () => {
|
|
236
|
+
const options = container.querySelectorAll(sel(pc, "select-item-option"));
|
|
237
|
+
options.forEach((opt) => {
|
|
238
|
+
const el = opt;
|
|
239
|
+
if (el.hasAttribute(attrName)) return;
|
|
240
|
+
const title = el.getAttribute("title") || el.textContent?.trim() || "";
|
|
241
|
+
el.setAttribute(attrName, `${prefix}-option-${title}`);
|
|
242
|
+
});
|
|
243
|
+
const treeNodes = container.querySelectorAll(sel(pc, "select-tree-treenode"));
|
|
244
|
+
treeNodes.forEach((node) => {
|
|
245
|
+
const el = node;
|
|
246
|
+
const content = el.querySelector(sel(pc, "select-tree-node-content-wrapper"));
|
|
247
|
+
const title = content?.getAttribute("title") || content?.textContent?.trim() || "";
|
|
248
|
+
if (content && !content.hasAttribute(attrName)) {
|
|
249
|
+
content.setAttribute(attrName, `${prefix}-tree-${title}`);
|
|
250
|
+
}
|
|
251
|
+
const switcher = el.querySelector(sel(pc, "select-tree-switcher"));
|
|
252
|
+
if (switcher && !switcher.hasAttribute(attrName)) {
|
|
253
|
+
const isOpen = switcher.classList.contains(cls(pc, "select-tree-switcher_open"));
|
|
254
|
+
const state = isOpen ? "collapse" : "expand";
|
|
255
|
+
switcher.setAttribute(attrName, `${prefix}-tree-switcher-${state}-${title}`);
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
};
|
|
259
|
+
injectAllItems();
|
|
260
|
+
if (!_observedContainers.has(container)) {
|
|
261
|
+
_observedContainers.add(container);
|
|
262
|
+
let timer = null;
|
|
263
|
+
const observer = new MutationObserver(() => {
|
|
264
|
+
if (timer !== null) clearTimeout(timer);
|
|
265
|
+
timer = setTimeout(() => {
|
|
266
|
+
injectAllItems();
|
|
267
|
+
}, 50);
|
|
268
|
+
});
|
|
269
|
+
observer.observe(container, { childList: true, subtree: true });
|
|
270
|
+
}
|
|
271
|
+
};
|
|
222
272
|
}
|
|
223
|
-
function
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const options = container.querySelectorAll(".ant-select-item-option");
|
|
229
|
-
options.forEach((opt) => {
|
|
230
|
-
const el = opt;
|
|
231
|
-
if (el.hasAttribute(attrName)) return;
|
|
232
|
-
const title = el.getAttribute("title") || el.textContent?.trim() || "";
|
|
233
|
-
el.setAttribute(attrName, `${prefix}-option-${title}`);
|
|
234
|
-
});
|
|
235
|
-
const treeNodes = container.querySelectorAll(".ant-select-tree-treenode");
|
|
236
|
-
treeNodes.forEach((node) => {
|
|
237
|
-
const el = node;
|
|
238
|
-
const content = el.querySelector(".ant-select-tree-node-content-wrapper");
|
|
239
|
-
const title = content?.getAttribute("title") || content?.textContent?.trim() || "";
|
|
240
|
-
if (content && !content.hasAttribute(attrName)) {
|
|
241
|
-
content.setAttribute(attrName, `${prefix}-tree-${title}`);
|
|
242
|
-
}
|
|
243
|
-
const switcher = el.querySelector(".ant-select-tree-switcher");
|
|
244
|
-
if (switcher && !switcher.hasAttribute(attrName)) {
|
|
245
|
-
const isOpen = switcher.classList.contains("ant-select-tree-switcher_open");
|
|
246
|
-
const state = isOpen ? "collapse" : "expand";
|
|
247
|
-
switcher.setAttribute(attrName, `${prefix}-tree-switcher-${state}-${title}`);
|
|
248
|
-
}
|
|
249
|
-
});
|
|
273
|
+
function buildPanels(pc) {
|
|
274
|
+
return {
|
|
275
|
+
[sel(pc, "picker-dropdown")]: makeInjectPickerPanel(pc),
|
|
276
|
+
[sel(pc, "cascader-dropdown")]: makeInjectCascaderPanel(pc),
|
|
277
|
+
[sel(pc, "select-dropdown")]: makeInjectSelectPanel(pc)
|
|
250
278
|
};
|
|
251
|
-
injectAllItems();
|
|
252
|
-
if (!_observedContainers.has(container)) {
|
|
253
|
-
_observedContainers.add(container);
|
|
254
|
-
let timer = null;
|
|
255
|
-
const observer = new MutationObserver(() => {
|
|
256
|
-
if (timer !== null) clearTimeout(timer);
|
|
257
|
-
timer = setTimeout(() => {
|
|
258
|
-
injectAllItems();
|
|
259
|
-
}, 50);
|
|
260
|
-
});
|
|
261
|
-
observer.observe(container, { childList: true, subtree: true });
|
|
262
|
-
}
|
|
263
279
|
}
|
|
264
|
-
function injectMenuItems(attrName, root = document) {
|
|
280
|
+
function injectMenuItems(attrName, root = document, pc) {
|
|
265
281
|
const itemRules = [
|
|
266
|
-
{ selector: "
|
|
267
|
-
{ selector: "
|
|
268
|
-
{ selector: "
|
|
282
|
+
{ selector: sel(pc, "menu-item"), prefix: "a-menu-item-" },
|
|
283
|
+
{ selector: sel(pc, "menu-submenu"), textSelector: sel(pc, "menu-submenu-title"), prefix: "a-sub-menu-" },
|
|
284
|
+
{ selector: sel(pc, "menu-item-group"), textSelector: sel(pc, "menu-item-group-title"), prefix: "a-menu-item-group-" }
|
|
269
285
|
];
|
|
270
286
|
for (const rule of itemRules) {
|
|
271
|
-
const
|
|
272
|
-
items.
|
|
287
|
+
const descendants = Array.from(root.querySelectorAll(rule.selector));
|
|
288
|
+
const items = root instanceof HTMLElement && root.matches(rule.selector) ? [root, ...descendants] : descendants;
|
|
289
|
+
for (const item of items) {
|
|
273
290
|
const el = item;
|
|
274
291
|
if (el.hasAttribute(attrName)) return;
|
|
275
292
|
const id = el.getAttribute("id");
|
|
@@ -282,21 +299,16 @@ function injectMenuItems(attrName, root = document) {
|
|
|
282
299
|
if (text) {
|
|
283
300
|
el.setAttribute(attrName, rule.prefix + text);
|
|
284
301
|
}
|
|
285
|
-
}
|
|
302
|
+
}
|
|
286
303
|
}
|
|
287
304
|
}
|
|
288
|
-
var DEFAULT_PANELS = {
|
|
289
|
-
".ant-picker-dropdown": injectPickerPanel,
|
|
290
|
-
".ant-cascader-dropdown": injectCascaderPanel,
|
|
291
|
-
".ant-select-dropdown": injectSelectPanel
|
|
292
|
-
};
|
|
293
305
|
var _observedContainers = /* @__PURE__ */ new WeakSet();
|
|
294
306
|
function getTriggerTestId(trigger, attrName) {
|
|
295
307
|
if (!trigger) return "unknown";
|
|
296
308
|
return trigger.getAttribute(attrName) || trigger.getAttribute("id") || "unknown";
|
|
297
309
|
}
|
|
298
|
-
function findActiveTrigger(attrName) {
|
|
299
|
-
const focused = document.querySelector("
|
|
310
|
+
function findActiveTrigger(attrName, pc) {
|
|
311
|
+
const focused = document.querySelector(sel(pc, "picker-focused"));
|
|
300
312
|
if (focused) {
|
|
301
313
|
if (focused.hasAttribute(attrName)) return focused;
|
|
302
314
|
const inner = focused.querySelector(`[${attrName}]`);
|
|
@@ -304,9 +316,9 @@ function findActiveTrigger(attrName) {
|
|
|
304
316
|
const input = focused.querySelector("input[id]");
|
|
305
317
|
if (input) return input;
|
|
306
318
|
}
|
|
307
|
-
const selectOpen = document.querySelector("
|
|
319
|
+
const selectOpen = document.querySelector(sel(pc, "select-open"));
|
|
308
320
|
if (selectOpen?.hasAttribute(attrName)) return selectOpen;
|
|
309
|
-
const cascader = document.querySelector("
|
|
321
|
+
const cascader = document.querySelector(sel(pc, "cascader-picker-focused"));
|
|
310
322
|
if (cascader?.hasAttribute(attrName)) return cascader;
|
|
311
323
|
const expanded = document.querySelector(
|
|
312
324
|
`[${attrName}][aria-expanded="true"]`
|
|
@@ -314,22 +326,75 @@ function findActiveTrigger(attrName) {
|
|
|
314
326
|
if (expanded) return expanded;
|
|
315
327
|
return null;
|
|
316
328
|
}
|
|
317
|
-
function
|
|
318
|
-
const
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
329
|
+
function injectSubElements(root, attrName, pc) {
|
|
330
|
+
const inputNumbers = root.matches(`${sel(pc, "input-number")}[${attrName}]`) ? [root] : Array.from(root.querySelectorAll(`${sel(pc, "input-number")}[${attrName}]`));
|
|
331
|
+
for (const wrapper of inputNumbers) {
|
|
332
|
+
if (!(wrapper instanceof HTMLElement)) continue;
|
|
333
|
+
const testId = wrapper.getAttribute(attrName) || "";
|
|
334
|
+
if (!testId) continue;
|
|
335
|
+
const input = wrapper.querySelector(sel(pc, "input-number-input"));
|
|
336
|
+
if (input && !input.hasAttribute(attrName)) {
|
|
337
|
+
input.setAttribute(attrName, testId);
|
|
326
338
|
}
|
|
339
|
+
const upHandler = wrapper.querySelector(sel(pc, "input-number-handler-up"));
|
|
340
|
+
if (upHandler && !upHandler.hasAttribute(attrName)) {
|
|
341
|
+
upHandler.setAttribute(attrName, `${testId}-up`);
|
|
342
|
+
}
|
|
343
|
+
const downHandler = wrapper.querySelector(sel(pc, "input-number-handler-down"));
|
|
344
|
+
if (downHandler && !downHandler.hasAttribute(attrName)) {
|
|
345
|
+
downHandler.setAttribute(attrName, `${testId}-down`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
const sliders = root.matches(`${sel(pc, "slider")}[${attrName}]`) ? [root] : Array.from(root.querySelectorAll(`${sel(pc, "slider")}[${attrName}]`));
|
|
349
|
+
for (const slider of sliders) {
|
|
350
|
+
if (!(slider instanceof HTMLElement)) continue;
|
|
351
|
+
const testId = slider.getAttribute(attrName) || "";
|
|
352
|
+
if (!testId) continue;
|
|
353
|
+
slider.querySelectorAll(sel(pc, "slider-handle")).forEach((h, i) => {
|
|
354
|
+
const el = h;
|
|
355
|
+
if (!el.hasAttribute(attrName)) {
|
|
356
|
+
el.setAttribute(attrName, `${testId}-handle-${i}`);
|
|
357
|
+
}
|
|
358
|
+
});
|
|
327
359
|
}
|
|
360
|
+
const rates = root.matches(`${sel(pc, "rate")}[${attrName}]`) ? [root] : Array.from(root.querySelectorAll(`${sel(pc, "rate")}[${attrName}]`));
|
|
361
|
+
for (const rate of rates) {
|
|
362
|
+
if (!(rate instanceof HTMLElement)) continue;
|
|
363
|
+
const testId = rate.getAttribute(attrName) || "";
|
|
364
|
+
if (!testId) continue;
|
|
365
|
+
rate.querySelectorAll(sel(pc, "rate-star")).forEach((s, i) => {
|
|
366
|
+
const el = s;
|
|
367
|
+
if (!el.hasAttribute(attrName)) {
|
|
368
|
+
el.setAttribute(attrName, `${testId}-star-${i}`);
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
const uploadByTestId = root.matches(`${sel(pc, "upload")}[${attrName}]`) ? [root] : Array.from(root.querySelectorAll(`${sel(pc, "upload")}[${attrName}]`));
|
|
373
|
+
const uploadById = uploadByTestId.length === 0 ? root.matches(`${sel(pc, "upload")}[id]`) ? [root] : Array.from(root.querySelectorAll(`${sel(pc, "upload")}[id]`)) : [];
|
|
374
|
+
for (const upload of [...uploadByTestId, ...uploadById]) {
|
|
375
|
+
if (!(upload instanceof HTMLElement)) continue;
|
|
376
|
+
const testId = upload.getAttribute(attrName) || upload.getAttribute("id") || "";
|
|
377
|
+
if (!testId) continue;
|
|
378
|
+
const input = upload.querySelector('input[type="file"]');
|
|
379
|
+
if (input && !input.hasAttribute(attrName)) {
|
|
380
|
+
input.setAttribute(attrName, `${testId}-input`);
|
|
381
|
+
if (!upload.hasAttribute(attrName)) {
|
|
382
|
+
upload.setAttribute(attrName, testId);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
function setupAntTestIds(opts = {}) {
|
|
388
|
+
const attrName = opts.attributeName ?? "data-testid";
|
|
389
|
+
const pc = opts.prefixCls ?? "ant";
|
|
390
|
+
const matchers = mergeMatchers(buildComponentMatchers(pc), opts.components);
|
|
391
|
+
const skipSelectors = buildSkipSelectors(pc);
|
|
392
|
+
const panels = { ...buildPanels(pc), ...opts.panels };
|
|
328
393
|
const counter = { value: 0 };
|
|
329
394
|
function processNode(node) {
|
|
330
395
|
if (!(node instanceof HTMLElement)) return;
|
|
331
|
-
injectComponentRoots(node, matchers, attrName, counter);
|
|
332
|
-
injectMenuItems(attrName, node);
|
|
396
|
+
injectComponentRoots(node, matchers, attrName, counter, skipSelectors);
|
|
397
|
+
injectMenuItems(attrName, node, pc);
|
|
333
398
|
for (const [selector, strategy] of Object.entries(panels)) {
|
|
334
399
|
const containers = node.matches(selector) ? [node] : Array.from(node.querySelectorAll(selector));
|
|
335
400
|
for (const container of containers) {
|
|
@@ -337,71 +402,14 @@ function setupAntTestIds(opts = {}) {
|
|
|
337
402
|
if (container.hasAttribute(attrName)) continue;
|
|
338
403
|
if (strategy) {
|
|
339
404
|
queueMicrotask(() => {
|
|
340
|
-
const trigger = findActiveTrigger(attrName);
|
|
405
|
+
const trigger = findActiveTrigger(attrName, pc);
|
|
341
406
|
const triggerTestId = getTriggerTestId(trigger, attrName);
|
|
342
407
|
strategy({ container, trigger, triggerTestId, attrName });
|
|
343
408
|
});
|
|
344
409
|
}
|
|
345
410
|
}
|
|
346
411
|
}
|
|
347
|
-
|
|
348
|
-
for (const inputNumber of inputNumbers) {
|
|
349
|
-
if (!(inputNumber instanceof HTMLElement)) continue;
|
|
350
|
-
const testId = inputNumber.getAttribute(attrName) || "";
|
|
351
|
-
if (!testId) continue;
|
|
352
|
-
const input = inputNumber.querySelector(".ant-input-number-input");
|
|
353
|
-
if (input && !input.hasAttribute(attrName)) {
|
|
354
|
-
input.setAttribute(attrName, testId);
|
|
355
|
-
}
|
|
356
|
-
const upHandler = inputNumber.querySelector(".ant-input-number-handler-up");
|
|
357
|
-
if (upHandler && !upHandler.hasAttribute(attrName)) {
|
|
358
|
-
upHandler.setAttribute(attrName, `${testId}-up`);
|
|
359
|
-
}
|
|
360
|
-
const downHandler = inputNumber.querySelector(".ant-input-number-handler-down");
|
|
361
|
-
if (downHandler && !downHandler.hasAttribute(attrName)) {
|
|
362
|
-
downHandler.setAttribute(attrName, `${testId}-down`);
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
const sliders = node.matches(`.ant-slider[${attrName}]`) ? [node] : Array.from(node.querySelectorAll(`.ant-slider[${attrName}]`));
|
|
366
|
-
for (const slider of sliders) {
|
|
367
|
-
if (!(slider instanceof HTMLElement)) continue;
|
|
368
|
-
const testId = slider.getAttribute(attrName) || "";
|
|
369
|
-
if (!testId) continue;
|
|
370
|
-
const handles = slider.querySelectorAll(".ant-slider-handle");
|
|
371
|
-
handles.forEach((h, i) => {
|
|
372
|
-
const el = h;
|
|
373
|
-
if (!el.hasAttribute(attrName)) {
|
|
374
|
-
el.setAttribute(attrName, `${testId}-handle-${i}`);
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
|
-
}
|
|
378
|
-
const rates = node.matches(`.ant-rate[${attrName}]`) ? [node] : Array.from(node.querySelectorAll(`.ant-rate[${attrName}]`));
|
|
379
|
-
for (const rate of rates) {
|
|
380
|
-
if (!(rate instanceof HTMLElement)) continue;
|
|
381
|
-
const testId = rate.getAttribute(attrName) || "";
|
|
382
|
-
if (!testId) continue;
|
|
383
|
-
const stars = rate.querySelectorAll(".ant-rate-star");
|
|
384
|
-
stars.forEach((s, i) => {
|
|
385
|
-
const el = s;
|
|
386
|
-
if (!el.hasAttribute(attrName)) {
|
|
387
|
-
el.setAttribute(attrName, `${testId}-star-${i}`);
|
|
388
|
-
}
|
|
389
|
-
});
|
|
390
|
-
}
|
|
391
|
-
const uploadByTestId = node.matches(`.ant-upload[${attrName}]`) ? [node] : Array.from(node.querySelectorAll(`.ant-upload[${attrName}]`));
|
|
392
|
-
const uploadById = uploadByTestId.length === 0 ? node.matches(".ant-upload[id]") ? [node] : Array.from(node.querySelectorAll(".ant-upload[id]")) : [];
|
|
393
|
-
for (const upload of [...uploadByTestId, ...uploadById]) {
|
|
394
|
-
if (!(upload instanceof HTMLElement)) continue;
|
|
395
|
-
const testId = upload.getAttribute(attrName) || upload.getAttribute("id") || "";
|
|
396
|
-
if (!testId) continue;
|
|
397
|
-
const input = upload.querySelector('input[type="file"]');
|
|
398
|
-
if (input && !input.hasAttribute(attrName)) {
|
|
399
|
-
input.setAttribute(attrName, `${testId}-input`);
|
|
400
|
-
if (!upload.hasAttribute(attrName)) {
|
|
401
|
-
upload.setAttribute(attrName, testId);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
}
|
|
412
|
+
injectSubElements(node, attrName, pc);
|
|
405
413
|
}
|
|
406
414
|
let pending = false;
|
|
407
415
|
let pendingNodes = [];
|
|
@@ -434,92 +442,34 @@ function setupAntTestIds(opts = {}) {
|
|
|
434
442
|
var setupAntDropdownTestIds = setupAntTestIds;
|
|
435
443
|
function injectCurrentDropdowns(opts = {}) {
|
|
436
444
|
const attrName = opts.attributeName ?? "data-testid";
|
|
437
|
-
const
|
|
445
|
+
const pc = opts.prefixCls ?? "ant";
|
|
446
|
+
const matchers = mergeMatchers(buildComponentMatchers(pc), opts.components);
|
|
447
|
+
const skipSelectors = buildSkipSelectors(pc);
|
|
448
|
+
const panels = { ...buildPanels(pc), ...opts.panels };
|
|
438
449
|
const counter = { value: 0 };
|
|
439
|
-
|
|
440
|
-
if (opts.components) {
|
|
441
|
-
const customKeys = new Set(Object.keys(opts.components));
|
|
442
|
-
matchers = matchers.filter((m) => !customKeys.has(m.selector));
|
|
443
|
-
for (const [selector, prefix] of Object.entries(opts.components)) {
|
|
444
|
-
matchers.push({ selector, prefix });
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
injectComponentRoots(document.body, matchers, attrName, counter);
|
|
450
|
+
injectComponentRoots(document.body, matchers, attrName, counter, skipSelectors);
|
|
448
451
|
for (const [selector, strategy] of Object.entries(panels)) {
|
|
449
452
|
const containers = document.querySelectorAll(selector);
|
|
450
453
|
containers.forEach((container) => {
|
|
451
454
|
if (!(container instanceof HTMLElement)) return;
|
|
452
455
|
if (container.hasAttribute(attrName)) return;
|
|
453
456
|
if (!strategy) return;
|
|
454
|
-
const trigger = findActiveTrigger(attrName);
|
|
457
|
+
const trigger = findActiveTrigger(attrName, pc);
|
|
455
458
|
const triggerTestId = getTriggerTestId(trigger, attrName);
|
|
456
459
|
strategy({ container, trigger, triggerTestId, attrName });
|
|
457
460
|
});
|
|
458
461
|
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
upHandler.setAttribute(attrName, `${testId}-up`);
|
|
471
|
-
}
|
|
472
|
-
const downHandler = inputNumber.querySelector(".ant-input-number-handler-down");
|
|
473
|
-
if (downHandler && !downHandler.hasAttribute(attrName)) {
|
|
474
|
-
downHandler.setAttribute(attrName, `${testId}-down`);
|
|
475
|
-
}
|
|
476
|
-
});
|
|
477
|
-
const sliders = document.querySelectorAll(`.ant-slider[${attrName}]`);
|
|
478
|
-
sliders.forEach((slider) => {
|
|
479
|
-
if (!(slider instanceof HTMLElement)) return;
|
|
480
|
-
const testId = slider.getAttribute(attrName) || "";
|
|
481
|
-
if (!testId) return;
|
|
482
|
-
const handles = slider.querySelectorAll(".ant-slider-handle");
|
|
483
|
-
handles.forEach((h, i) => {
|
|
484
|
-
const el = h;
|
|
485
|
-
if (!el.hasAttribute(attrName)) {
|
|
486
|
-
el.setAttribute(attrName, `${testId}-handle-${i}`);
|
|
487
|
-
}
|
|
488
|
-
});
|
|
489
|
-
});
|
|
490
|
-
const rates = document.querySelectorAll(`.ant-rate[${attrName}]`);
|
|
491
|
-
rates.forEach((rate) => {
|
|
492
|
-
if (!(rate instanceof HTMLElement)) return;
|
|
493
|
-
const testId = rate.getAttribute(attrName) || "";
|
|
494
|
-
if (!testId) return;
|
|
495
|
-
const stars = rate.querySelectorAll(".ant-rate-star");
|
|
496
|
-
stars.forEach((s, i) => {
|
|
497
|
-
const el = s;
|
|
498
|
-
if (!el.hasAttribute(attrName)) {
|
|
499
|
-
el.setAttribute(attrName, `${testId}-star-${i}`);
|
|
500
|
-
}
|
|
501
|
-
});
|
|
502
|
-
});
|
|
503
|
-
const uploads = [
|
|
504
|
-
...Array.from(document.querySelectorAll(`.ant-upload[${attrName}]`)),
|
|
505
|
-
...Array.from(document.querySelectorAll(".ant-upload[id]"))
|
|
506
|
-
];
|
|
507
|
-
const seen = /* @__PURE__ */ new Set();
|
|
508
|
-
uploads.forEach((upload) => {
|
|
509
|
-
if (!(upload instanceof HTMLElement)) return;
|
|
510
|
-
if (seen.has(upload)) return;
|
|
511
|
-
seen.add(upload);
|
|
512
|
-
const testId = upload.getAttribute(attrName) || upload.getAttribute("id") || "";
|
|
513
|
-
if (!testId) return;
|
|
514
|
-
const input = upload.querySelector('input[type="file"]');
|
|
515
|
-
if (input && !input.hasAttribute(attrName)) {
|
|
516
|
-
input.setAttribute(attrName, `${testId}-input`);
|
|
517
|
-
if (!upload.hasAttribute(attrName)) {
|
|
518
|
-
upload.setAttribute(attrName, testId);
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
});
|
|
522
|
-
injectMenuItems(attrName);
|
|
462
|
+
injectSubElements(document.body, attrName, pc);
|
|
463
|
+
injectMenuItems(attrName, document, pc);
|
|
464
|
+
}
|
|
465
|
+
function mergeMatchers(defaults, customs) {
|
|
466
|
+
if (!customs) return defaults;
|
|
467
|
+
const customKeys = new Set(Object.keys(customs));
|
|
468
|
+
const filtered = defaults.filter((m) => !customKeys.has(m.selector));
|
|
469
|
+
for (const [selector, prefix] of Object.entries(customs)) {
|
|
470
|
+
filtered.push({ selector, prefix });
|
|
471
|
+
}
|
|
472
|
+
return filtered;
|
|
523
473
|
}
|
|
524
474
|
export {
|
|
525
475
|
injectCurrentDropdowns,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-vue-testid",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"description": "Vite plugin to auto-inject data-testid into Vue component templates for E2E testing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -47,4 +47,4 @@
|
|
|
47
47
|
"typescript": "~6.0.2",
|
|
48
48
|
"vite": "^8.0.12"
|
|
49
49
|
}
|
|
50
|
-
}
|
|
50
|
+
}
|