* Wait for an element matching a text pattern among multiple candidates. * @param {string} containerSelector - Selector for candidate elements * @param {RegExp} textPattern - Regex to match against textContent * @param {number} timeout - Max wait time in ms * @returns {Promise }
(containerSelector, textPattern, timeout = 10000)
| 135 | * @returns {Promise<Element>} |
| 136 | */ |
| 137 | function waitForElementByText(containerSelector, textPattern, timeout = 10000) { |
| 138 | return new Promise((resolve, reject) => { |
| 139 | throwIfStopped(); |
| 140 | |
| 141 | function search() { |
| 142 | const candidates = document.querySelectorAll(containerSelector); |
| 143 | for (const el of candidates) { |
| 144 | if (textPattern.test(el.textContent)) { |
| 145 | return el; |
| 146 | } |
| 147 | } |
| 148 | return null; |
| 149 | } |
| 150 | |
| 151 | const existing = search(); |
| 152 | if (existing) { |
| 153 | console.log(LOG_PREFIX, `立即按文本找到元素: ${containerSelector} 匹配 ${textPattern}`); |
| 154 | log(`已按文本找到元素:${textPattern}`); |
| 155 | resolve(existing); |
| 156 | return; |
| 157 | } |
| 158 | |
| 159 | console.log(LOG_PREFIX, `等待文本匹配: ${containerSelector} / ${textPattern}`); |
| 160 | log(`正在等待包含文本的元素:${textPattern}...`); |
| 161 | |
| 162 | let settled = false; |
| 163 | let stopTimer = null; |
| 164 | const cleanup = () => { |
| 165 | if (settled) return; |
| 166 | settled = true; |
| 167 | observer.disconnect(); |
| 168 | clearTimeout(timer); |
| 169 | clearTimeout(stopTimer); |
| 170 | }; |
| 171 | |
| 172 | const observer = new MutationObserver(() => { |
| 173 | if (flowStopped) { |
| 174 | cleanup(); |
| 175 | reject(new Error(STOP_ERROR_MESSAGE)); |
| 176 | return; |
| 177 | } |
| 178 | const el = search(); |
| 179 | if (el) { |
| 180 | cleanup(); |
| 181 | console.log(LOG_PREFIX, `等待后按文本找到元素: ${textPattern}`); |
| 182 | log(`已按文本找到元素:${textPattern}`); |
| 183 | resolve(el); |
| 184 | } |
| 185 | }); |
| 186 | |
| 187 | observer.observe(document.body || document.documentElement, { |
| 188 | childList: true, |
| 189 | subtree: true, |
| 190 | }); |
| 191 | |
| 192 | const timer = setTimeout(() => { |
| 193 | cleanup(); |
| 194 | const msg = `在 ${location.href} 的 ${containerSelector} 中等待文本 "${textPattern}" 超时,已超过 ${timeout}ms`; |
no test coverage detected