github.com/MontFerret/ferret@v0.18.0/pkg/drivers/cdp/templates/wait.go (about) 1 package templates 2 3 import ( 4 "fmt" 5 6 "github.com/mafredri/cdp/protocol/runtime" 7 8 "github.com/MontFerret/ferret/pkg/drivers" 9 "github.com/MontFerret/ferret/pkg/drivers/cdp/eval" 10 "github.com/MontFerret/ferret/pkg/runtime/core" 11 "github.com/MontFerret/ferret/pkg/runtime/values" 12 ) 13 14 const ( 15 waitExistenceFragment = `(el, op, ...args) => { 16 const actual = %s; // check 17 18 // presence 19 if (op === 0) { 20 if (actual != null) { 21 return true; 22 } 23 } else { 24 if (actual == null) { 25 return true; 26 } 27 } 28 29 // null means we need to repeat 30 return null; 31 }` 32 33 waitEqualityFragment = `(el, expected, op, ...args) => { 34 const actual = %s; // check 35 36 // presence 37 if (op === 0) { 38 if (actual === expected) { 39 return true; 40 } 41 } else { 42 if (actual !== expected) { 43 return true; 44 } 45 } 46 47 // null means we need to repeat 48 return null; 49 }` 50 51 waitExistenceBySelectorFragment = `(el, selector, op, ...args) => { 52 // selector 53 %s 54 55 if (found == null) { 56 return false; 57 } 58 59 const actual = %s; // check 60 61 // presence 62 if (op === 0) { 63 if (actual != null) { 64 return true; 65 } 66 } else { 67 if (actual == null) { 68 return true; 69 } 70 } 71 72 // null means we need to repeat 73 return null; 74 }` 75 76 waitEqualityBySelectorFragment = `(el, selector, expected, op, ...args) => { 77 // selector 78 %s 79 80 if (found == null) { 81 return false; 82 } 83 84 const actual = %s; // check 85 86 // presence 87 if (op === 0) { 88 if (actual === expected) { 89 return true; 90 } 91 } else { 92 if (actual !== expected) { 93 return true; 94 } 95 } 96 97 // null means we need to repeat 98 return null; 99 }` 100 101 waitExistenceBySelectorAllFragment = `(el, selector, op, ...args) => { 102 // selector 103 %s 104 105 if (found == null || !found || found.length === 0) { 106 return false; 107 } 108 109 let resultCount = 0; 110 111 found.forEach((el) => { 112 let actual = %s; // check 113 114 // when 115 // presence 116 if (op === 0) { 117 if (actual != null) { 118 resultCount++; 119 } 120 } else { 121 if (actual == null) { 122 resultCount++; 123 } 124 } 125 }); 126 127 if (resultCount === found.length) { 128 return true; 129 } 130 131 // null means we need to repeat 132 return null; 133 }` 134 135 waitEqualityBySelectorAllFragment = `(el, selector, expected, op, ...args) => { 136 // selector 137 %s 138 139 if (found == null || !found || found.length === 0) { 140 return false; 141 } 142 143 let resultCount = 0; 144 145 found.forEach((el) => { 146 let actual = %s; // check 147 148 // when 149 // presence 150 if (op === 0) { 151 if (actual === expected) { 152 resultCount++; 153 } 154 } else { 155 if (actual !== expected) { 156 resultCount++; 157 } 158 } 159 }); 160 161 if (resultCount === found.length) { 162 return true; 163 } 164 165 // null means we need to repeat 166 return null; 167 }` 168 ) 169 170 func partialWaitExistence(id runtime.RemoteObjectID, when drivers.WaitEvent, fragment string) *eval.Function { 171 return eval.F(fmt.Sprintf(waitExistenceFragment, fragment)). 172 WithArgRef(id). 173 WithArg(int(when)) 174 } 175 176 func partialWaitEquality(id runtime.RemoteObjectID, expected core.Value, when drivers.WaitEvent, fragment string) *eval.Function { 177 return eval.F(fmt.Sprintf(waitEqualityFragment, fragment)). 178 WithArgRef(id). 179 WithArgValue(expected). 180 WithArg(int(when)) 181 } 182 183 func partialWaitExistenceBySelector(id runtime.RemoteObjectID, selector drivers.QuerySelector, when drivers.WaitEvent, fragment string) *eval.Function { 184 var tmpl string 185 186 if selector.Kind() == drivers.CSSSelector { 187 tmpl = fmt.Sprintf(waitExistenceBySelectorFragment, queryCSSSelectorFragment, fragment) 188 } else { 189 tmpl = fmt.Sprintf(waitExistenceBySelectorFragment, xpathAsElementFragment, fragment) 190 } 191 192 return eval.F(tmpl). 193 WithArgRef(id). 194 WithArgSelector(selector). 195 WithArg(int(when)) 196 } 197 198 func partialWaitEqualityBySelector(id runtime.RemoteObjectID, selector drivers.QuerySelector, expected core.Value, when drivers.WaitEvent, fragment string) *eval.Function { 199 var tmpl string 200 201 if selector.Kind() == drivers.CSSSelector { 202 tmpl = fmt.Sprintf(waitEqualityBySelectorFragment, queryCSSSelectorFragment, fragment) 203 } else { 204 tmpl = fmt.Sprintf(waitEqualityBySelectorFragment, xpathAsElementFragment, fragment) 205 } 206 207 return eval.F(tmpl). 208 WithArgRef(id). 209 WithArgSelector(selector). 210 WithArgValue(expected). 211 WithArg(int(when)) 212 } 213 214 func partialWaitExistenceBySelectorAll(id runtime.RemoteObjectID, selector drivers.QuerySelector, when drivers.WaitEvent, fragment string) *eval.Function { 215 var tmpl string 216 217 if selector.Kind() == drivers.CSSSelector { 218 tmpl = fmt.Sprintf(waitExistenceBySelectorAllFragment, queryCSSSelectorAllFragment, fragment) 219 } else { 220 tmpl = fmt.Sprintf(waitExistenceBySelectorAllFragment, xpathAsElementArrayFragment, fragment) 221 } 222 223 return eval.F(tmpl). 224 WithArgRef(id). 225 WithArgSelector(selector). 226 WithArg(int(when)) 227 } 228 229 func partialWaitEqualityBySelectorAll(id runtime.RemoteObjectID, selector drivers.QuerySelector, expected core.Value, when drivers.WaitEvent, fragment string) *eval.Function { 230 var tmpl string 231 232 if selector.Kind() == drivers.CSSSelector { 233 tmpl = fmt.Sprintf(waitEqualityBySelectorAllFragment, queryCSSSelectorAllFragment, fragment) 234 } else { 235 tmpl = fmt.Sprintf(waitEqualityBySelectorAllFragment, xpathAsElementArrayFragment, fragment) 236 } 237 238 return eval.F(tmpl). 239 WithArgRef(id). 240 WithArgSelector(selector). 241 WithArgValue(expected). 242 WithArg(int(when)) 243 } 244 245 const waitForElementByCSSFragment = `el.querySelector(args[0])` 246 247 var waitForElementByXPathFragment = fmt.Sprintf(`(() => { 248 const selector = args[0]; 249 250 %s 251 252 return found; 253 })()`, xpathAsElementFragment) 254 255 func WaitForElement(id runtime.RemoteObjectID, selector drivers.QuerySelector, when drivers.WaitEvent) *eval.Function { 256 var tmpl string 257 258 if selector.Kind() == drivers.CSSSelector { 259 tmpl = waitForElementByCSSFragment 260 } else { 261 tmpl = waitForElementByXPathFragment 262 } 263 264 return partialWaitExistence(id, when, tmpl).WithArgSelector(selector) 265 } 266 267 const waitForElementAllByCSSFragment = `(function() { 268 const elements = el.querySelector(args[0]); 269 270 return elements.length; 271 })()` 272 273 var waitForElementAllByXPathFragment = fmt.Sprintf(`(function() { 274 const selector = args[0]; 275 276 %s 277 278 return found; 279 })()`, xpathAsElementArrayFragment) 280 281 func WaitForElementAll(id runtime.RemoteObjectID, selector drivers.QuerySelector, when drivers.WaitEvent) *eval.Function { 282 var tmpl string 283 284 if selector.Kind() == drivers.CSSSelector { 285 tmpl = waitForElementAllByCSSFragment 286 } else { 287 tmpl = waitForElementAllByXPathFragment 288 } 289 290 return partialWaitEquality(id, values.ZeroInt, when, tmpl).WithArgSelector(selector) 291 } 292 293 const waitForClassFragment = `el.className.split(' ').find(i => i === args[0]);` 294 295 func WaitForClass(id runtime.RemoteObjectID, class values.String, when drivers.WaitEvent) *eval.Function { 296 return partialWaitExistence(id, when, waitForClassFragment).WithArgValue(class) 297 } 298 299 const waitForClassBySelectorFragment = `found.className.split(' ').find(i => i === args[0]);` 300 301 func WaitForClassBySelector(id runtime.RemoteObjectID, selector drivers.QuerySelector, class values.String, when drivers.WaitEvent) *eval.Function { 302 return partialWaitExistenceBySelector(id, selector, when, waitForClassBySelectorFragment).WithArgValue(class) 303 } 304 305 func WaitForClassBySelectorAll(id runtime.RemoteObjectID, selector drivers.QuerySelector, class values.String, when drivers.WaitEvent) *eval.Function { 306 return partialWaitExistenceBySelectorAll(id, selector, when, waitForClassFragment).WithArgValue(class) 307 } 308 309 const waitForAttributeFragment = `el.getAttribute(args[0])` 310 311 func WaitForAttribute(id runtime.RemoteObjectID, name values.String, expected core.Value, when drivers.WaitEvent) *eval.Function { 312 return partialWaitEquality(id, expected, when, waitForAttributeFragment).WithArgValue(name) 313 } 314 315 const waitForAttributeBySelectorFragment = `found.getAttribute(args[0])` 316 317 func WaitForAttributeBySelector(id runtime.RemoteObjectID, selector drivers.QuerySelector, name core.Value, expected core.Value, when drivers.WaitEvent) *eval.Function { 318 return partialWaitEqualityBySelector(id, selector, expected, when, waitForAttributeBySelectorFragment).WithArgValue(name) 319 } 320 321 func WaitForAttributeBySelectorAll(id runtime.RemoteObjectID, selector drivers.QuerySelector, name values.String, expected core.Value, when drivers.WaitEvent) *eval.Function { 322 return partialWaitEqualityBySelectorAll(id, selector, expected, when, waitForAttributeFragment).WithArgValue(name) 323 } 324 325 const waitForStyleFragment = `(function getStyles() { 326 const styles = window.getComputedStyle(el); 327 return styles[args[0]]; 328 })()` 329 330 func WaitForStyle(id runtime.RemoteObjectID, name values.String, expected core.Value, when drivers.WaitEvent) *eval.Function { 331 return partialWaitEquality(id, expected, when, waitForStyleFragment).WithArgValue(name) 332 } 333 334 const waitForStyleBySelectorFragment = `(function getStyles() { 335 const styles = window.getComputedStyle(found); 336 return styles[args[0]]; 337 })()` 338 339 func WaitForStyleBySelector(id runtime.RemoteObjectID, selector drivers.QuerySelector, name values.String, expected core.Value, when drivers.WaitEvent) *eval.Function { 340 return partialWaitEqualityBySelector(id, selector, expected, when, waitForStyleBySelectorFragment).WithArgValue(name) 341 } 342 343 func WaitForStyleBySelectorAll(id runtime.RemoteObjectID, selector drivers.QuerySelector, name values.String, expected core.Value, when drivers.WaitEvent) *eval.Function { 344 return partialWaitEqualityBySelectorAll(id, selector, expected, when, waitForStyleFragment).WithArgValue(name) 345 }