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  }