mirror of
https://github.com/MontFerret/ferret.git
synced 2025-06-23 00:28:10 +02:00
Added Context to HTML methods (#235)
* Added Context to HTML methods * Fixed unit tests * Updated timeout * Fixed WAIT_CLASS timeout
This commit is contained in:
@ -53,7 +53,20 @@ func New(logger zerolog.Logger, settings Settings) *Runner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Runner) Run() error {
|
func (r *Runner) Run() error {
|
||||||
results, err := r.runQueries(r.settings.Dir)
|
ctx := context.Background()
|
||||||
|
|
||||||
|
ctx = drivers.WithContext(
|
||||||
|
ctx,
|
||||||
|
cdp.NewDriver(cdp.WithAddress(r.settings.CDPAddress)),
|
||||||
|
)
|
||||||
|
|
||||||
|
ctx = drivers.WithContext(
|
||||||
|
ctx,
|
||||||
|
http.NewDriver(),
|
||||||
|
drivers.AsDefault(),
|
||||||
|
)
|
||||||
|
|
||||||
|
results, err := r.runQueries(ctx, r.settings.Dir)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -83,7 +96,7 @@ func (r *Runner) Run() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Runner) runQueries(dir string) ([]Result, error) {
|
func (r *Runner) runQueries(ctx context.Context, dir string) ([]Result, error) {
|
||||||
files, err := ioutil.ReadDir(dir)
|
files, err := ioutil.ReadDir(dir)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -126,13 +139,30 @@ func (r *Runner) runQueries(dir string) ([]Result, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
results = append(results, r.runQuery(c, fName, string(b)))
|
r.logger.Info().Timestamp().Str("name", fName).Msg("Running test")
|
||||||
|
|
||||||
|
result := r.runQuery(ctx, c, fName, string(b))
|
||||||
|
|
||||||
|
if result.err == nil {
|
||||||
|
r.logger.Info().
|
||||||
|
Timestamp().
|
||||||
|
Str("file", result.name).
|
||||||
|
Msg("Test passed")
|
||||||
|
} else {
|
||||||
|
r.logger.Error().
|
||||||
|
Timestamp().
|
||||||
|
Err(result.err).
|
||||||
|
Str("file", result.name).
|
||||||
|
Msg("Test failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
results = append(results, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Runner) runQuery(c *compiler.FqlCompiler, name, script string) Result {
|
func (r *Runner) runQuery(ctx context.Context, c *compiler.FqlCompiler, name, script string) Result {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
p, err := c.Compile(script)
|
p, err := c.Compile(script)
|
||||||
@ -145,20 +175,6 @@ func (r *Runner) runQuery(c *compiler.FqlCompiler, name, script string) Result {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
ctx = drivers.WithContext(
|
|
||||||
ctx,
|
|
||||||
cdp.NewDriver(cdp.WithAddress(r.settings.CDPAddress)),
|
|
||||||
)
|
|
||||||
|
|
||||||
ctx = drivers.WithContext(
|
|
||||||
ctx,
|
|
||||||
http.NewDriver(),
|
|
||||||
drivers.AsDefault(),
|
|
||||||
)
|
|
||||||
|
|
||||||
r.logger.Info().Timestamp().Str("name", name).Msg("Running test")
|
|
||||||
|
|
||||||
out, err := p.Run(
|
out, err := p.Run(
|
||||||
ctx,
|
ctx,
|
||||||
runtime.WithLog(zerolog.ConsoleWriter{Out: os.Stdout}),
|
runtime.WithLog(zerolog.ConsoleWriter{Out: os.Stdout}),
|
||||||
@ -207,20 +223,9 @@ func (r *Runner) report(results []Result) Summary {
|
|||||||
|
|
||||||
for _, res := range results {
|
for _, res := range results {
|
||||||
if res.err != nil {
|
if res.err != nil {
|
||||||
r.logger.Error().
|
|
||||||
Timestamp().
|
|
||||||
Err(res.err).
|
|
||||||
Str("file", res.name).
|
|
||||||
Dur("time", res.duration).
|
|
||||||
Msg("Test failed")
|
|
||||||
|
|
||||||
failed++
|
failed++
|
||||||
} else {
|
} else {
|
||||||
r.logger.Info().
|
|
||||||
Timestamp().
|
|
||||||
Str("file", res.name).
|
|
||||||
Dur("time", res.duration).
|
|
||||||
Msg("Test passed")
|
|
||||||
|
|
||||||
passed++
|
passed++
|
||||||
}
|
}
|
||||||
|
@ -273,32 +273,32 @@ func (doc *HTMLDocument) Length() values.Int {
|
|||||||
return doc.element.Length()
|
return doc.element.Length()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) GetChildNodes() core.Value {
|
func (doc *HTMLDocument) GetChildNodes(ctx context.Context) core.Value {
|
||||||
doc.Lock()
|
doc.Lock()
|
||||||
defer doc.Unlock()
|
defer doc.Unlock()
|
||||||
|
|
||||||
return doc.element.GetChildNodes()
|
return doc.element.GetChildNodes(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) GetChildNode(idx values.Int) core.Value {
|
func (doc *HTMLDocument) GetChildNode(ctx context.Context, idx values.Int) core.Value {
|
||||||
doc.Lock()
|
doc.Lock()
|
||||||
defer doc.Unlock()
|
defer doc.Unlock()
|
||||||
|
|
||||||
return doc.element.GetChildNode(idx)
|
return doc.element.GetChildNode(ctx, idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) QuerySelector(selector values.String) core.Value {
|
func (doc *HTMLDocument) QuerySelector(ctx context.Context, selector values.String) core.Value {
|
||||||
doc.Lock()
|
doc.Lock()
|
||||||
defer doc.Unlock()
|
defer doc.Unlock()
|
||||||
|
|
||||||
return doc.element.QuerySelector(selector)
|
return doc.element.QuerySelector(ctx, selector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) QuerySelectorAll(selector values.String) core.Value {
|
func (doc *HTMLDocument) QuerySelectorAll(ctx context.Context, selector values.String) core.Value {
|
||||||
doc.Lock()
|
doc.Lock()
|
||||||
defer doc.Unlock()
|
defer doc.Unlock()
|
||||||
|
|
||||||
return doc.element.QuerySelectorAll(selector)
|
return doc.element.QuerySelectorAll(ctx, selector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) DocumentElement() drivers.HTMLElement {
|
func (doc *HTMLDocument) DocumentElement() drivers.HTMLElement {
|
||||||
@ -315,26 +315,27 @@ func (doc *HTMLDocument) GetURL() core.Value {
|
|||||||
return doc.url
|
return doc.url
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) SetURL(url values.String) error {
|
func (doc *HTMLDocument) SetURL(ctx context.Context, url values.String) error {
|
||||||
return doc.Navigate(url, values.Int(DefaultTimeout))
|
return doc.Navigate(ctx, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) CountBySelector(selector values.String) values.Int {
|
func (doc *HTMLDocument) CountBySelector(ctx context.Context, selector values.String) values.Int {
|
||||||
doc.Lock()
|
doc.Lock()
|
||||||
defer doc.Unlock()
|
defer doc.Unlock()
|
||||||
|
|
||||||
return doc.element.CountBySelector(selector)
|
return doc.element.CountBySelector(ctx, selector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) ExistsBySelector(selector values.String) values.Boolean {
|
func (doc *HTMLDocument) ExistsBySelector(ctx context.Context, selector values.String) values.Boolean {
|
||||||
doc.Lock()
|
doc.Lock()
|
||||||
defer doc.Unlock()
|
defer doc.Unlock()
|
||||||
|
|
||||||
return doc.element.ExistsBySelector(selector)
|
return doc.element.ExistsBySelector(ctx, selector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) ClickBySelector(selector values.String) (values.Boolean, error) {
|
func (doc *HTMLDocument) ClickBySelector(ctx context.Context, selector values.String) (values.Boolean, error) {
|
||||||
res, err := eval.Eval(
|
res, err := eval.Eval(
|
||||||
|
ctx,
|
||||||
doc.client,
|
doc.client,
|
||||||
fmt.Sprintf(`
|
fmt.Sprintf(`
|
||||||
var el = document.querySelector(%s);
|
var el = document.querySelector(%s);
|
||||||
@ -360,8 +361,9 @@ func (doc *HTMLDocument) ClickBySelector(selector values.String) (values.Boolean
|
|||||||
return values.False, nil
|
return values.False, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) ClickBySelectorAll(selector values.String) (values.Boolean, error) {
|
func (doc *HTMLDocument) ClickBySelectorAll(ctx context.Context, selector values.String) (values.Boolean, error) {
|
||||||
res, err := eval.Eval(
|
res, err := eval.Eval(
|
||||||
|
ctx,
|
||||||
doc.client,
|
doc.client,
|
||||||
fmt.Sprintf(`
|
fmt.Sprintf(`
|
||||||
var elements = document.querySelectorAll(%s);
|
var elements = document.querySelectorAll(%s);
|
||||||
@ -389,12 +391,11 @@ func (doc *HTMLDocument) ClickBySelectorAll(selector values.String) (values.Bool
|
|||||||
return values.False, nil
|
return values.False, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) InputBySelector(selector values.String, value core.Value, delay values.Int) (values.Boolean, error) {
|
func (doc *HTMLDocument) InputBySelector(ctx context.Context, selector values.String, value core.Value, delay values.Int) (values.Boolean, error) {
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
valStr := value.String()
|
valStr := value.String()
|
||||||
|
|
||||||
res, err := eval.Eval(
|
res, err := eval.Eval(
|
||||||
|
ctx,
|
||||||
doc.client,
|
doc.client,
|
||||||
fmt.Sprintf(`
|
fmt.Sprintf(`
|
||||||
var el = document.querySelector(%s);
|
var el = document.querySelector(%s);
|
||||||
@ -423,9 +424,11 @@ func (doc *HTMLDocument) InputBySelector(selector values.String, value core.Valu
|
|||||||
for _, ch := range valStr {
|
for _, ch := range valStr {
|
||||||
for _, ev := range []string{"keyDown", "keyUp"} {
|
for _, ev := range []string{"keyDown", "keyUp"} {
|
||||||
ke := input.NewDispatchKeyEventArgs(ev).SetText(string(ch))
|
ke := input.NewDispatchKeyEventArgs(ev).SetText(string(ch))
|
||||||
|
|
||||||
if err := doc.client.Input.DispatchKeyEvent(ctx, ke); err != nil {
|
if err := doc.client.Input.DispatchKeyEvent(ctx, ke); err != nil {
|
||||||
return values.False, err
|
return values.False, err
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(delayMs * time.Millisecond)
|
time.Sleep(delayMs * time.Millisecond)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -433,8 +436,9 @@ func (doc *HTMLDocument) InputBySelector(selector values.String, value core.Valu
|
|||||||
return values.True, nil
|
return values.True, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) SelectBySelector(selector values.String, value *values.Array) (*values.Array, error) {
|
func (doc *HTMLDocument) SelectBySelector(ctx context.Context, selector values.String, value *values.Array) (*values.Array, error) {
|
||||||
res, err := eval.Eval(
|
res, err := eval.Eval(
|
||||||
|
ctx,
|
||||||
doc.client,
|
doc.client,
|
||||||
fmt.Sprintf(`
|
fmt.Sprintf(`
|
||||||
var element = document.querySelector(%s);
|
var element = document.querySelector(%s);
|
||||||
@ -479,11 +483,8 @@ func (doc *HTMLDocument) SelectBySelector(selector values.String, value *values.
|
|||||||
return nil, core.TypeError(types.Array, res.Type())
|
return nil, core.TypeError(types.Array, res.Type())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) HoverBySelector(selector values.String) error {
|
func (doc *HTMLDocument) HoverBySelector(ctx context.Context, selector values.String) error {
|
||||||
ctx, cancel := contextWithTimeout()
|
err := doc.ScrollBySelector(ctx, selector)
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
err := doc.ScrollBySelector(selector)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -518,7 +519,7 @@ func (doc *HTMLDocument) HoverBySelector(selector values.String) error {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) WaitForSelector(selector values.String, timeout values.Int) error {
|
func (doc *HTMLDocument) WaitForSelector(ctx context.Context, selector values.String) error {
|
||||||
task := events.NewEvalWaitTask(
|
task := events.NewEvalWaitTask(
|
||||||
doc.client,
|
doc.client,
|
||||||
fmt.Sprintf(`
|
fmt.Sprintf(`
|
||||||
@ -529,16 +530,15 @@ func (doc *HTMLDocument) WaitForSelector(selector values.String, timeout values.
|
|||||||
// null means we need to repeat
|
// null means we need to repeat
|
||||||
return null;
|
return null;
|
||||||
`, eval.ParamString(selector.String())),
|
`, eval.ParamString(selector.String())),
|
||||||
time.Millisecond*time.Duration(timeout),
|
|
||||||
events.DefaultPolling,
|
events.DefaultPolling,
|
||||||
)
|
)
|
||||||
|
|
||||||
_, err := task.Run()
|
_, err := task.Run(ctx)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) WaitForClassBySelector(selector, class values.String, timeout values.Int) error {
|
func (doc *HTMLDocument) WaitForClassBySelector(ctx context.Context, selector, class values.String) error {
|
||||||
task := events.NewEvalWaitTask(
|
task := events.NewEvalWaitTask(
|
||||||
doc.client,
|
doc.client,
|
||||||
fmt.Sprintf(`
|
fmt.Sprintf(`
|
||||||
@ -558,16 +558,15 @@ func (doc *HTMLDocument) WaitForClassBySelector(selector, class values.String, t
|
|||||||
eval.ParamString(selector.String()),
|
eval.ParamString(selector.String()),
|
||||||
eval.ParamString(class.String()),
|
eval.ParamString(class.String()),
|
||||||
),
|
),
|
||||||
time.Millisecond*time.Duration(timeout),
|
|
||||||
events.DefaultPolling,
|
events.DefaultPolling,
|
||||||
)
|
)
|
||||||
|
|
||||||
_, err := task.Run()
|
_, err := task.Run(ctx)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) WaitForClassBySelectorAll(selector, class values.String, timeout values.Int) error {
|
func (doc *HTMLDocument) WaitForClassBySelectorAll(ctx context.Context, selector, class values.String) error {
|
||||||
task := events.NewEvalWaitTask(
|
task := events.NewEvalWaitTask(
|
||||||
doc.client,
|
doc.client,
|
||||||
fmt.Sprintf(`
|
fmt.Sprintf(`
|
||||||
@ -593,23 +592,17 @@ func (doc *HTMLDocument) WaitForClassBySelectorAll(selector, class values.String
|
|||||||
eval.ParamString(selector.String()),
|
eval.ParamString(selector.String()),
|
||||||
eval.ParamString(class.String()),
|
eval.ParamString(class.String()),
|
||||||
),
|
),
|
||||||
time.Millisecond*time.Duration(timeout),
|
|
||||||
events.DefaultPolling,
|
events.DefaultPolling,
|
||||||
)
|
)
|
||||||
|
|
||||||
_, err := task.Run()
|
_, err := task.Run(ctx)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) WaitForNavigation(timeout values.Int) error {
|
func (doc *HTMLDocument) WaitForNavigation(ctx context.Context) error {
|
||||||
// do not wait
|
|
||||||
if timeout == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
onEvent := make(chan struct{})
|
onEvent := make(chan struct{})
|
||||||
listener := func(_ interface{}) {
|
listener := func(_ context.Context, _ interface{}) {
|
||||||
close(onEvent)
|
close(onEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -620,17 +613,16 @@ func (doc *HTMLDocument) WaitForNavigation(timeout values.Int) error {
|
|||||||
select {
|
select {
|
||||||
case <-onEvent:
|
case <-onEvent:
|
||||||
return nil
|
return nil
|
||||||
case <-time.After(time.Millisecond * time.Duration(timeout)):
|
case <-ctx.Done():
|
||||||
return core.ErrTimeout
|
return core.ErrTimeout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) Navigate(url values.String, timeout values.Int) error {
|
func (doc *HTMLDocument) Navigate(ctx context.Context, url values.String) error {
|
||||||
if url == "" {
|
if url == "" {
|
||||||
url = BlankPageURL
|
url = BlankPageURL
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
repl, err := doc.client.Page.Navigate(ctx, page.NewNavigateArgs(url.String()))
|
repl, err := doc.client.Page.Navigate(ctx, page.NewNavigateArgs(url.String()))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -641,11 +633,10 @@ func (doc *HTMLDocument) Navigate(url values.String, timeout values.Int) error {
|
|||||||
return errors.New(*repl.ErrorText)
|
return errors.New(*repl.ErrorText)
|
||||||
}
|
}
|
||||||
|
|
||||||
return doc.WaitForNavigation(timeout)
|
return doc.WaitForNavigation(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) NavigateBack(skip values.Int, timeout values.Int) (values.Boolean, error) {
|
func (doc *HTMLDocument) NavigateBack(ctx context.Context, skip values.Int) (values.Boolean, error) {
|
||||||
ctx := context.Background()
|
|
||||||
history, err := doc.client.Page.GetNavigationHistory(ctx)
|
history, err := doc.client.Page.GetNavigationHistory(ctx)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -675,7 +666,7 @@ func (doc *HTMLDocument) NavigateBack(skip values.Int, timeout values.Int) (valu
|
|||||||
return values.False, err
|
return values.False, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = doc.WaitForNavigation(timeout)
|
err = doc.WaitForNavigation(ctx)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return values.False, err
|
return values.False, err
|
||||||
@ -684,8 +675,7 @@ func (doc *HTMLDocument) NavigateBack(skip values.Int, timeout values.Int) (valu
|
|||||||
return values.True, nil
|
return values.True, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) NavigateForward(skip values.Int, timeout values.Int) (values.Boolean, error) {
|
func (doc *HTMLDocument) NavigateForward(ctx context.Context, skip values.Int) (values.Boolean, error) {
|
||||||
ctx := context.Background()
|
|
||||||
history, err := doc.client.Page.GetNavigationHistory(ctx)
|
history, err := doc.client.Page.GetNavigationHistory(ctx)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -718,7 +708,7 @@ func (doc *HTMLDocument) NavigateForward(skip values.Int, timeout values.Int) (v
|
|||||||
return values.False, err
|
return values.False, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = doc.WaitForNavigation(timeout)
|
err = doc.WaitForNavigation(ctx)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return values.False, err
|
return values.False, err
|
||||||
@ -727,9 +717,7 @@ func (doc *HTMLDocument) NavigateForward(skip values.Int, timeout values.Int) (v
|
|||||||
return values.True, nil
|
return values.True, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) PrintToPDF(params drivers.PDFParams) (values.Binary, error) {
|
func (doc *HTMLDocument) PrintToPDF(ctx context.Context, params drivers.PDFParams) (values.Binary, error) {
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
args := page.NewPrintToPDFArgs()
|
args := page.NewPrintToPDFArgs()
|
||||||
args.
|
args.
|
||||||
SetLandscape(bool(params.Landscape)).
|
SetLandscape(bool(params.Landscape)).
|
||||||
@ -787,8 +775,7 @@ func (doc *HTMLDocument) PrintToPDF(params drivers.PDFParams) (values.Binary, er
|
|||||||
return values.NewBinary(reply.Data), nil
|
return values.NewBinary(reply.Data), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) CaptureScreenshot(params drivers.ScreenshotParams) (values.Binary, error) {
|
func (doc *HTMLDocument) CaptureScreenshot(ctx context.Context, params drivers.ScreenshotParams) (values.Binary, error) {
|
||||||
ctx := context.Background()
|
|
||||||
metrics, err := doc.client.Page.GetLayoutMetrics(ctx)
|
metrics, err := doc.client.Page.GetLayoutMetrics(ctx)
|
||||||
|
|
||||||
if params.Format == drivers.ScreenshotFormatJPEG && params.Quality < 0 && params.Quality > 100 {
|
if params.Format == drivers.ScreenshotFormatJPEG && params.Quality < 0 && params.Quality > 100 {
|
||||||
@ -836,8 +823,8 @@ func (doc *HTMLDocument) CaptureScreenshot(params drivers.ScreenshotParams) (val
|
|||||||
return values.NewBinary(reply.Data), nil
|
return values.NewBinary(reply.Data), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) ScrollTop() error {
|
func (doc *HTMLDocument) ScrollTop(ctx context.Context) error {
|
||||||
_, err := eval.Eval(doc.client, `
|
_, err := eval.Eval(ctx, doc.client, `
|
||||||
window.scrollTo({
|
window.scrollTo({
|
||||||
left: 0,
|
left: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
@ -848,8 +835,8 @@ func (doc *HTMLDocument) ScrollTop() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) ScrollBottom() error {
|
func (doc *HTMLDocument) ScrollBottom(ctx context.Context) error {
|
||||||
_, err := eval.Eval(doc.client, `
|
_, err := eval.Eval(ctx, doc.client, `
|
||||||
window.scrollTo({
|
window.scrollTo({
|
||||||
left: 0,
|
left: 0,
|
||||||
top: window.document.body.scrollHeight,
|
top: window.document.body.scrollHeight,
|
||||||
@ -860,8 +847,8 @@ func (doc *HTMLDocument) ScrollBottom() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) ScrollBySelector(selector values.String) error {
|
func (doc *HTMLDocument) ScrollBySelector(ctx context.Context, selector values.String) error {
|
||||||
_, err := eval.Eval(doc.client, fmt.Sprintf(`
|
_, err := eval.Eval(ctx, doc.client, fmt.Sprintf(`
|
||||||
var el = document.querySelector(%s);
|
var el = document.querySelector(%s);
|
||||||
if (el == null) {
|
if (el == null) {
|
||||||
throw new Error("element not found");
|
throw new Error("element not found");
|
||||||
@ -876,13 +863,10 @@ func (doc *HTMLDocument) ScrollBySelector(selector values.String) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) handlePageLoad(_ interface{}) {
|
func (doc *HTMLDocument) handlePageLoad(ctx context.Context, _ interface{}) {
|
||||||
doc.Lock()
|
doc.Lock()
|
||||||
defer doc.Unlock()
|
defer doc.Unlock()
|
||||||
|
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
node, err := getRootElement(ctx, doc.client)
|
node, err := getRootElement(ctx, doc.client)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -924,7 +908,7 @@ func (doc *HTMLDocument) handlePageLoad(_ interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) handleError(val interface{}) {
|
func (doc *HTMLDocument) handleError(_ context.Context, val interface{}) {
|
||||||
err, ok := val.(error)
|
err, ok := val.(error)
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -25,8 +25,6 @@ import (
|
|||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
)
|
)
|
||||||
|
|
||||||
const DefaultTimeout = time.Second * 30
|
|
||||||
|
|
||||||
var emptyNodeID = dom.NodeID(0)
|
var emptyNodeID = dom.NodeID(0)
|
||||||
var emptyBackendID = dom.BackendNodeID(0)
|
var emptyBackendID = dom.BackendNodeID(0)
|
||||||
|
|
||||||
@ -201,7 +199,7 @@ func (el *HTMLElement) Type() core.Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) MarshalJSON() ([]byte, error) {
|
func (el *HTMLElement) MarshalJSON() ([]byte, error) {
|
||||||
val, err := el.innerText.Read()
|
val, err := el.innerText.Read(context.Background())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -211,7 +209,7 @@ func (el *HTMLElement) MarshalJSON() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) String() string {
|
func (el *HTMLElement) String() string {
|
||||||
return el.InnerHTML().String()
|
return el.InnerHTML(context.Background()).String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) Compare(other core.Value) int64 {
|
func (el *HTMLElement) Compare(other core.Value) int64 {
|
||||||
@ -219,7 +217,9 @@ func (el *HTMLElement) Compare(other core.Value) int64 {
|
|||||||
case drivers.HTMLElementType:
|
case drivers.HTMLElementType:
|
||||||
other := other.(drivers.HTMLElement)
|
other := other.(drivers.HTMLElement)
|
||||||
|
|
||||||
return el.InnerHTML().Compare(other.InnerHTML())
|
ctx := context.Background()
|
||||||
|
|
||||||
|
return el.InnerHTML(ctx).Compare(other.InnerHTML(ctx))
|
||||||
default:
|
default:
|
||||||
return drivers.Compare(el.Type(), other.Type())
|
return drivers.Compare(el.Type(), other.Type())
|
||||||
}
|
}
|
||||||
@ -258,14 +258,11 @@ func (el *HTMLElement) SetIn(ctx context.Context, path []core.Value, value core.
|
|||||||
return common.SetInElement(ctx, el, path, value)
|
return common.SetInElement(ctx, el, path, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) GetValue() core.Value {
|
func (el *HTMLElement) GetValue(ctx context.Context) core.Value {
|
||||||
if !el.IsConnected() {
|
if !el.IsConnected() {
|
||||||
return el.value
|
return el.value
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
val, err := eval.Property(ctx, el.client, el.id.objectID, "value")
|
val, err := eval.Property(ctx, el.client, el.id.objectID, "value")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -279,15 +276,12 @@ func (el *HTMLElement) GetValue() core.Value {
|
|||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) SetValue(value core.Value) error {
|
func (el *HTMLElement) SetValue(ctx context.Context, value core.Value) error {
|
||||||
if !el.IsConnected() {
|
if !el.IsConnected() {
|
||||||
// TODO: Return an error
|
// TODO: Return an error
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
return el.client.DOM.SetNodeValue(ctx, dom.NewSetNodeValueArgs(el.id.nodeID, value.String()))
|
return el.client.DOM.SetNodeValue(ctx, dom.NewSetNodeValueArgs(el.id.nodeID, value.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,8 +297,8 @@ func (el *HTMLElement) Length() values.Int {
|
|||||||
return values.NewInt(len(el.children))
|
return values.NewInt(len(el.children))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) GetAttributes() core.Value {
|
func (el *HTMLElement) GetAttributes(ctx context.Context) core.Value {
|
||||||
val, err := el.attributes.Read()
|
val, err := el.attributes.Read(ctx)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return values.None
|
return values.None
|
||||||
@ -314,8 +308,8 @@ func (el *HTMLElement) GetAttributes() core.Value {
|
|||||||
return val.Copy()
|
return val.Copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) GetAttribute(name values.String) core.Value {
|
func (el *HTMLElement) GetAttribute(ctx context.Context, name values.String) core.Value {
|
||||||
attrs, err := el.attributes.Read()
|
attrs, err := el.attributes.Read(ctx)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return values.None
|
return values.None
|
||||||
@ -330,15 +324,15 @@ func (el *HTMLElement) GetAttribute(name values.String) core.Value {
|
|||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) SetAttribute(name, value values.String) error {
|
func (el *HTMLElement) SetAttribute(ctx context.Context, name, value values.String) error {
|
||||||
return el.client.DOM.SetAttributeValue(
|
return el.client.DOM.SetAttributeValue(
|
||||||
context.Background(),
|
ctx,
|
||||||
dom.NewSetAttributeValueArgs(el.id.nodeID, string(name), string(value)),
|
dom.NewSetAttributeValueArgs(el.id.nodeID, string(name), string(value)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) GetChildNodes() core.Value {
|
func (el *HTMLElement) GetChildNodes(ctx context.Context) core.Value {
|
||||||
val, err := el.loadedChildren.Read()
|
val, err := el.loadedChildren.Read(ctx)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return values.NewArray(0)
|
return values.NewArray(0)
|
||||||
@ -347,9 +341,8 @@ func (el *HTMLElement) GetChildNodes() core.Value {
|
|||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) GetChildNode(idx values.Int) core.Value {
|
func (el *HTMLElement) GetChildNode(ctx context.Context, idx values.Int) core.Value {
|
||||||
// TODO: Add lazy loading
|
val, err := el.loadedChildren.Read(ctx)
|
||||||
val, err := el.loadedChildren.Read()
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return values.None
|
return values.None
|
||||||
@ -358,14 +351,11 @@ func (el *HTMLElement) GetChildNode(idx values.Int) core.Value {
|
|||||||
return val.(*values.Array).Get(idx)
|
return val.(*values.Array).Get(idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) QuerySelector(selector values.String) core.Value {
|
func (el *HTMLElement) QuerySelector(ctx context.Context, selector values.String) core.Value {
|
||||||
if !el.IsConnected() {
|
if !el.IsConnected() {
|
||||||
return values.None
|
return values.None
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
|
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
|
||||||
selectorArgs := dom.NewQuerySelectorArgs(el.id.nodeID, selector.String())
|
selectorArgs := dom.NewQuerySelectorArgs(el.id.nodeID, selector.String())
|
||||||
found, err := el.client.DOM.QuerySelector(ctx, selectorArgs)
|
found, err := el.client.DOM.QuerySelector(ctx, selectorArgs)
|
||||||
@ -399,14 +389,11 @@ func (el *HTMLElement) QuerySelector(selector values.String) core.Value {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) QuerySelectorAll(selector values.String) core.Value {
|
func (el *HTMLElement) QuerySelectorAll(ctx context.Context, selector values.String) core.Value {
|
||||||
if !el.IsConnected() {
|
if !el.IsConnected() {
|
||||||
return values.NewArray(0)
|
return values.NewArray(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
|
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
|
||||||
selectorArgs := dom.NewQuerySelectorAllArgs(el.id.nodeID, selector.String())
|
selectorArgs := dom.NewQuerySelectorAllArgs(el.id.nodeID, selector.String())
|
||||||
res, err := el.client.DOM.QuerySelectorAll(ctx, selectorArgs)
|
res, err := el.client.DOM.QuerySelectorAll(ctx, selectorArgs)
|
||||||
@ -455,8 +442,8 @@ func (el *HTMLElement) QuerySelectorAll(selector values.String) core.Value {
|
|||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) InnerText() values.String {
|
func (el *HTMLElement) InnerText(ctx context.Context) values.String {
|
||||||
val, err := el.innerText.Read()
|
val, err := el.innerText.Read(ctx)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return values.EmptyString
|
return values.EmptyString
|
||||||
@ -469,14 +456,11 @@ func (el *HTMLElement) InnerText() values.String {
|
|||||||
return val.(values.String)
|
return val.(values.String)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) InnerTextBySelector(selector values.String) values.String {
|
func (el *HTMLElement) InnerTextBySelector(ctx context.Context, selector values.String) values.String {
|
||||||
if !el.IsConnected() {
|
if !el.IsConnected() {
|
||||||
return values.EmptyString
|
return values.EmptyString
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
|
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
|
||||||
found, err := el.client.DOM.QuerySelector(ctx, dom.NewQuerySelectorArgs(el.id.nodeID, selector.String()))
|
found, err := el.client.DOM.QuerySelector(ctx, dom.NewQuerySelectorArgs(el.id.nodeID, selector.String()))
|
||||||
|
|
||||||
@ -534,10 +518,7 @@ func (el *HTMLElement) InnerTextBySelector(selector values.String) values.String
|
|||||||
return values.NewString(text.String())
|
return values.NewString(text.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) InnerTextBySelectorAll(selector values.String) *values.Array {
|
func (el *HTMLElement) InnerTextBySelectorAll(ctx context.Context, selector values.String) *values.Array {
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
|
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
|
||||||
res, err := el.client.DOM.QuerySelectorAll(ctx, dom.NewQuerySelectorAllArgs(el.id.nodeID, selector.String()))
|
res, err := el.client.DOM.QuerySelectorAll(ctx, dom.NewQuerySelectorAllArgs(el.id.nodeID, selector.String()))
|
||||||
|
|
||||||
@ -595,21 +576,18 @@ func (el *HTMLElement) InnerTextBySelectorAll(selector values.String) *values.Ar
|
|||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) InnerHTML() values.String {
|
func (el *HTMLElement) InnerHTML(_ context.Context) values.String {
|
||||||
el.mu.Lock()
|
el.mu.Lock()
|
||||||
defer el.mu.Unlock()
|
defer el.mu.Unlock()
|
||||||
|
|
||||||
return el.innerHTML
|
return el.innerHTML
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) InnerHTMLBySelector(selector values.String) values.String {
|
func (el *HTMLElement) InnerHTMLBySelector(ctx context.Context, selector values.String) values.String {
|
||||||
if !el.IsConnected() {
|
if !el.IsConnected() {
|
||||||
return values.EmptyString
|
return values.EmptyString
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
|
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
|
||||||
found, err := el.client.DOM.QuerySelector(ctx, dom.NewQuerySelectorArgs(el.id.nodeID, selector.String()))
|
found, err := el.client.DOM.QuerySelector(ctx, dom.NewQuerySelectorArgs(el.id.nodeID, selector.String()))
|
||||||
|
|
||||||
@ -636,10 +614,7 @@ func (el *HTMLElement) InnerHTMLBySelector(selector values.String) values.String
|
|||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) InnerHTMLBySelectorAll(selector values.String) *values.Array {
|
func (el *HTMLElement) InnerHTMLBySelectorAll(ctx context.Context, selector values.String) *values.Array {
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
|
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
|
||||||
selectorArgs := dom.NewQuerySelectorAllArgs(el.id.nodeID, selector.String())
|
selectorArgs := dom.NewQuerySelectorAllArgs(el.id.nodeID, selector.String())
|
||||||
res, err := el.client.DOM.QuerySelectorAll(ctx, selectorArgs)
|
res, err := el.client.DOM.QuerySelectorAll(ctx, selectorArgs)
|
||||||
@ -674,14 +649,11 @@ func (el *HTMLElement) InnerHTMLBySelectorAll(selector values.String) *values.Ar
|
|||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) CountBySelector(selector values.String) values.Int {
|
func (el *HTMLElement) CountBySelector(ctx context.Context, selector values.String) values.Int {
|
||||||
if !el.IsConnected() {
|
if !el.IsConnected() {
|
||||||
return values.ZeroInt
|
return values.ZeroInt
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
|
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
|
||||||
selectorArgs := dom.NewQuerySelectorAllArgs(el.id.nodeID, selector.String())
|
selectorArgs := dom.NewQuerySelectorAllArgs(el.id.nodeID, selector.String())
|
||||||
res, err := el.client.DOM.QuerySelectorAll(ctx, selectorArgs)
|
res, err := el.client.DOM.QuerySelectorAll(ctx, selectorArgs)
|
||||||
@ -697,14 +669,11 @@ func (el *HTMLElement) CountBySelector(selector values.String) values.Int {
|
|||||||
return values.NewInt(len(res.NodeIDs))
|
return values.NewInt(len(res.NodeIDs))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) ExistsBySelector(selector values.String) values.Boolean {
|
func (el *HTMLElement) ExistsBySelector(ctx context.Context, selector values.String) values.Boolean {
|
||||||
if !el.IsConnected() {
|
if !el.IsConnected() {
|
||||||
return values.False
|
return values.False
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
|
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
|
||||||
selectorArgs := dom.NewQuerySelectorArgs(el.id.nodeID, selector.String())
|
selectorArgs := dom.NewQuerySelectorArgs(el.id.nodeID, selector.String())
|
||||||
res, err := el.client.DOM.QuerySelector(ctx, selectorArgs)
|
res, err := el.client.DOM.QuerySelector(ctx, selectorArgs)
|
||||||
@ -724,10 +693,10 @@ func (el *HTMLElement) ExistsBySelector(selector values.String) values.Boolean {
|
|||||||
return values.True
|
return values.True
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) WaitForClass(class values.String, timeout values.Int) error {
|
func (el *HTMLElement) WaitForClass(ctx context.Context, class values.String) error {
|
||||||
task := events.NewWaitTask(
|
task := events.NewWaitTask(
|
||||||
func() (core.Value, error) {
|
func(ctx2 context.Context) (core.Value, error) {
|
||||||
current := el.GetAttribute("class")
|
current := el.GetAttribute(ctx2, "class")
|
||||||
|
|
||||||
if current.Type() != types.String {
|
if current.Type() != types.String {
|
||||||
return values.None, nil
|
return values.None, nil
|
||||||
@ -745,27 +714,19 @@ func (el *HTMLElement) WaitForClass(class values.String, timeout values.Int) err
|
|||||||
|
|
||||||
return values.None, nil
|
return values.None, nil
|
||||||
},
|
},
|
||||||
time.Millisecond*time.Duration(timeout),
|
|
||||||
events.DefaultPolling,
|
events.DefaultPolling,
|
||||||
)
|
)
|
||||||
|
|
||||||
_, err := task.Run()
|
_, err := task.Run(ctx)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) Click() (values.Boolean, error) {
|
func (el *HTMLElement) Click(ctx context.Context) (values.Boolean, error) {
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
return events.DispatchEvent(ctx, el.client, el.id.objectID, "click")
|
return events.DispatchEvent(ctx, el.client, el.id.objectID, "click")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) Input(value core.Value, delay values.Int) error {
|
func (el *HTMLElement) Input(ctx context.Context, value core.Value, delay values.Int) error {
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
if err := el.client.DOM.Focus(ctx, dom.NewFocusArgs().SetObjectID(el.id.objectID)); err != nil {
|
if err := el.client.DOM.Focus(ctx, dom.NewFocusArgs().SetObjectID(el.id.objectID)); err != nil {
|
||||||
el.logError(err).Msg("failed to focus")
|
el.logError(err).Msg("failed to focus")
|
||||||
|
|
||||||
@ -795,7 +756,7 @@ func (el *HTMLElement) Input(value core.Value, delay values.Int) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) Select(value *values.Array) (*values.Array, error) {
|
func (el *HTMLElement) Select(ctx context.Context, value *values.Array) (*values.Array, error) {
|
||||||
var attrID = "data-ferret-select"
|
var attrID = "data-ferret-select"
|
||||||
|
|
||||||
if el.NodeName() != "SELECT" {
|
if el.NodeName() != "SELECT" {
|
||||||
@ -808,9 +769,6 @@ func (el *HTMLElement) Select(value *values.Array) (*values.Array, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
err = el.client.DOM.SetAttributeValue(ctx, dom.NewSetAttributeValueArgs(el.id.nodeID, attrID, id.String()))
|
err = el.client.DOM.SetAttributeValue(ctx, dom.NewSetAttributeValueArgs(el.id.nodeID, attrID, id.String()))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -818,6 +776,7 @@ func (el *HTMLElement) Select(value *values.Array) (*values.Array, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res, err := eval.Eval(
|
res, err := eval.Eval(
|
||||||
|
ctx,
|
||||||
el.client,
|
el.client,
|
||||||
fmt.Sprintf(`
|
fmt.Sprintf(`
|
||||||
var el = document.querySelector('[%s="%s"]');
|
var el = document.querySelector('[%s="%s"]');
|
||||||
@ -865,7 +824,7 @@ func (el *HTMLElement) Select(value *values.Array) (*values.Array, error) {
|
|||||||
return nil, core.TypeError(types.Array, res.Type())
|
return nil, core.TypeError(types.Array, res.Type())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) ScrollIntoView() error {
|
func (el *HTMLElement) ScrollIntoView(ctx context.Context) error {
|
||||||
var attrID = "data-ferret-scroll"
|
var attrID = "data-ferret-scroll"
|
||||||
|
|
||||||
id, err := uuid.NewV4()
|
id, err := uuid.NewV4()
|
||||||
@ -874,45 +833,43 @@ func (el *HTMLElement) ScrollIntoView() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
err = el.client.DOM.SetAttributeValue(ctx, dom.NewSetAttributeValueArgs(el.id.nodeID, attrID, id.String()))
|
err = el.client.DOM.SetAttributeValue(ctx, dom.NewSetAttributeValueArgs(el.id.nodeID, attrID, id.String()))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = eval.Eval(el.client, fmt.Sprintf(`
|
_, err = eval.Eval(
|
||||||
var el = document.querySelector('[%s="%s"]');
|
ctx,
|
||||||
if (el == null) {
|
el.client,
|
||||||
throw new Error('element not found');
|
fmt.Sprintf(`
|
||||||
}
|
var el = document.querySelector('[%s="%s"]');
|
||||||
el.scrollIntoView({
|
if (el == null) {
|
||||||
behavior: 'instant',
|
throw new Error('element not found');
|
||||||
inline: 'center',
|
}
|
||||||
block: 'center'
|
|
||||||
});
|
el.scrollIntoView({
|
||||||
`,
|
behavior: 'instant',
|
||||||
attrID,
|
inline: 'center',
|
||||||
id.String(),
|
block: 'center'
|
||||||
), false, false)
|
});
|
||||||
|
`,
|
||||||
|
attrID,
|
||||||
|
id.String(),
|
||||||
|
), false, false)
|
||||||
|
|
||||||
el.client.DOM.RemoveAttribute(ctx, dom.NewRemoveAttributeArgs(el.id.nodeID, attrID))
|
el.client.DOM.RemoveAttribute(ctx, dom.NewRemoveAttributeArgs(el.id.nodeID, attrID))
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) Hover() error {
|
func (el *HTMLElement) Hover(ctx context.Context) error {
|
||||||
err := el.ScrollIntoView()
|
err := el.ScrollIntoView(ctx)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
q, err := getClickablePoint(ctx, el.client, el.id)
|
q, err := getClickablePoint(ctx, el.client, el.id)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -932,11 +889,8 @@ func (el *HTMLElement) IsConnected() values.Boolean {
|
|||||||
return el.connected
|
return el.connected
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) loadInnerText() (core.Value, error) {
|
func (el *HTMLElement) loadInnerText(ctx context.Context) (core.Value, error) {
|
||||||
if el.IsConnected() {
|
if el.IsConnected() {
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
text, err := loadInnerText(ctx, el.client, el.id)
|
text, err := loadInnerText(ctx, el.client, el.id)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -948,7 +902,7 @@ func (el *HTMLElement) loadInnerText() (core.Value, error) {
|
|||||||
// and just parse cached innerHTML
|
// and just parse cached innerHTML
|
||||||
}
|
}
|
||||||
|
|
||||||
h := el.InnerHTML()
|
h := el.InnerHTML(ctx)
|
||||||
|
|
||||||
if h == values.EmptyString {
|
if h == values.EmptyString {
|
||||||
return h, nil
|
return h, nil
|
||||||
@ -965,18 +919,15 @@ func (el *HTMLElement) loadInnerText() (core.Value, error) {
|
|||||||
return parsed, nil
|
return parsed, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) loadAttrs() (core.Value, error) {
|
func (el *HTMLElement) loadAttrs(_ context.Context) (core.Value, error) {
|
||||||
return parseAttrs(el.rawAttrs), nil
|
return parseAttrs(el.rawAttrs), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) loadChildren() (core.Value, error) {
|
func (el *HTMLElement) loadChildren(ctx context.Context) (core.Value, error) {
|
||||||
if !el.IsConnected() {
|
if !el.IsConnected() {
|
||||||
return values.NewArray(0), nil
|
return values.NewArray(0), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
loaded := values.NewArray(len(el.children))
|
loaded := values.NewArray(len(el.children))
|
||||||
|
|
||||||
for _, childID := range el.children {
|
for _, childID := range el.children {
|
||||||
@ -1001,11 +952,11 @@ func (el *HTMLElement) loadChildren() (core.Value, error) {
|
|||||||
return loaded, nil
|
return loaded, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) handlePageReload(_ interface{}) {
|
func (el *HTMLElement) handlePageReload(_ context.Context, _ interface{}) {
|
||||||
el.Close()
|
el.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) handleAttrModified(message interface{}) {
|
func (el *HTMLElement) handleAttrModified(ctx context.Context, message interface{}) {
|
||||||
reply, ok := message.(*dom.AttributeModifiedReply)
|
reply, ok := message.(*dom.AttributeModifiedReply)
|
||||||
|
|
||||||
// well....
|
// well....
|
||||||
@ -1018,7 +969,7 @@ func (el *HTMLElement) handleAttrModified(message interface{}) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
el.attributes.Write(func(v core.Value, err error) {
|
el.attributes.Write(ctx, func(v core.Value, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
el.logError(err).Msg("failed to update element")
|
el.logError(err).Msg("failed to update element")
|
||||||
|
|
||||||
@ -1035,7 +986,7 @@ func (el *HTMLElement) handleAttrModified(message interface{}) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) handleAttrRemoved(message interface{}) {
|
func (el *HTMLElement) handleAttrRemoved(ctx context.Context, message interface{}) {
|
||||||
reply, ok := message.(*dom.AttributeRemovedReply)
|
reply, ok := message.(*dom.AttributeRemovedReply)
|
||||||
|
|
||||||
// well....
|
// well....
|
||||||
@ -1054,7 +1005,7 @@ func (el *HTMLElement) handleAttrRemoved(message interface{}) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
el.attributes.Write(func(v core.Value, err error) {
|
el.attributes.Write(ctx, func(v core.Value, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
el.logError(err).Msg("failed to update element")
|
el.logError(err).Msg("failed to update element")
|
||||||
|
|
||||||
@ -1071,7 +1022,7 @@ func (el *HTMLElement) handleAttrRemoved(message interface{}) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) handleChildrenCountChanged(message interface{}) {
|
func (el *HTMLElement) handleChildrenCountChanged(ctx context.Context, message interface{}) {
|
||||||
reply, ok := message.(*dom.ChildNodeCountUpdatedReply)
|
reply, ok := message.(*dom.ChildNodeCountUpdatedReply)
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -1082,9 +1033,6 @@ func (el *HTMLElement) handleChildrenCountChanged(message interface{}) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
node, err := el.client.DOM.DescribeNode(
|
node, err := el.client.DOM.DescribeNode(
|
||||||
ctx,
|
ctx,
|
||||||
dom.NewDescribeNodeArgs().SetObjectID(el.id.objectID),
|
dom.NewDescribeNodeArgs().SetObjectID(el.id.objectID),
|
||||||
@ -1102,7 +1050,7 @@ func (el *HTMLElement) handleChildrenCountChanged(message interface{}) {
|
|||||||
el.children = createChildrenArray(node.Node.Children)
|
el.children = createChildrenArray(node.Node.Children)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) handleChildInserted(message interface{}) {
|
func (el *HTMLElement) handleChildInserted(ctx context.Context, message interface{}) {
|
||||||
reply, ok := message.(*dom.ChildNodeInsertedReply)
|
reply, ok := message.(*dom.ChildNodeInsertedReply)
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -1143,10 +1091,7 @@ func (el *HTMLElement) handleChildInserted(message interface{}) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
el.loadedChildren.Write(func(v core.Value, err error) {
|
el.loadedChildren.Write(ctx, func(v core.Value, err error) {
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
loadedArr := v.(*values.Array)
|
loadedArr := v.(*values.Array)
|
||||||
loadedEl, err := LoadElement(ctx, el.logger, el.client, el.events, nextID, emptyBackendID)
|
loadedEl, err := LoadElement(ctx, el.logger, el.client, el.events, nextID, emptyBackendID)
|
||||||
|
|
||||||
@ -1171,7 +1116,7 @@ func (el *HTMLElement) handleChildInserted(message interface{}) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (el *HTMLElement) handleChildRemoved(message interface{}) {
|
func (el *HTMLElement) handleChildRemoved(ctx context.Context, message interface{}) {
|
||||||
reply, ok := message.(*dom.ChildNodeRemovedReply)
|
reply, ok := message.(*dom.ChildNodeRemovedReply)
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -1206,7 +1151,7 @@ func (el *HTMLElement) handleChildRemoved(message interface{}) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
el.loadedChildren.Write(func(v core.Value, err error) {
|
el.loadedChildren.Write(ctx, func(v core.Value, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
el.logger.Error().
|
el.logger.Error().
|
||||||
Timestamp().
|
Timestamp().
|
||||||
@ -1217,9 +1162,6 @@ func (el *HTMLElement) handleChildRemoved(message interface{}) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := contextWithTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
loadedArr := v.(*values.Array)
|
loadedArr := v.(*values.Array)
|
||||||
loadedArr.RemoveAt(values.NewInt(targetIDx))
|
loadedArr.RemoveAt(values.NewInt(targetIDx))
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||||
"github.com/mafredri/cdp"
|
"github.com/mafredri/cdp"
|
||||||
@ -18,13 +19,13 @@ func ParamString(param string) string {
|
|||||||
return "`" + param + "`"
|
return "`" + param + "`"
|
||||||
}
|
}
|
||||||
|
|
||||||
func Eval(client *cdp.Client, exp string, ret bool, async bool) (core.Value, error) {
|
func Eval(ctx context.Context, client *cdp.Client, exp string, ret bool, async bool) (core.Value, error) {
|
||||||
args := runtime.
|
args := runtime.
|
||||||
NewEvaluateArgs(PrepareEval(exp)).
|
NewEvaluateArgs(PrepareEval(exp)).
|
||||||
SetReturnByValue(ret).
|
SetReturnByValue(ret).
|
||||||
SetAwaitPromise(async)
|
SetAwaitPromise(async)
|
||||||
|
|
||||||
out, err := client.Runtime.Evaluate(context.Background(), args)
|
out, err := client.Runtime.Evaluate(ctx, args)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return values.None, err
|
return values.None, err
|
||||||
|
@ -2,17 +2,19 @@ package events
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/MontFerret/ferret/pkg/drivers"
|
||||||
|
"reflect"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||||
"github.com/mafredri/cdp/protocol/dom"
|
"github.com/mafredri/cdp/protocol/dom"
|
||||||
"github.com/mafredri/cdp/protocol/page"
|
"github.com/mafredri/cdp/protocol/page"
|
||||||
"reflect"
|
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Event int
|
Event int
|
||||||
|
|
||||||
EventListener func(message interface{})
|
EventListener func(ctx context.Context, message interface{})
|
||||||
|
|
||||||
EventBroker struct {
|
EventBroker struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
@ -275,7 +277,11 @@ func (broker *EventBroker) emit(ctx context.Context, event Event, message interf
|
|||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
listener(message)
|
ctx2, fn := drivers.WithDefaultTimeout(ctx)
|
||||||
|
|
||||||
|
listener(ctx2, message)
|
||||||
|
|
||||||
|
fn()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package events_test
|
package events_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/MontFerret/ferret/pkg/drivers/cdp/events"
|
"github.com/MontFerret/ferret/pkg/drivers/cdp/events"
|
||||||
"github.com/mafredri/cdp/protocol/dom"
|
"github.com/mafredri/cdp/protocol/dom"
|
||||||
"github.com/mafredri/cdp/protocol/page"
|
"github.com/mafredri/cdp/protocol/page"
|
||||||
@ -198,7 +199,7 @@ func TestEventBroker(t *testing.T) {
|
|||||||
b := NewTestEventBroker()
|
b := NewTestEventBroker()
|
||||||
|
|
||||||
StressTest(func() error {
|
StressTest(func() error {
|
||||||
b.AddEventListener(events.EventLoad, func(message interface{}) {})
|
b.AddEventListener(events.EventLoad, func(ctx context.Context, message interface{}) {})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}, 500)
|
}, 500)
|
||||||
@ -210,7 +211,7 @@ func TestEventBroker(t *testing.T) {
|
|||||||
defer b.Stop()
|
defer b.Stop()
|
||||||
|
|
||||||
StressTest(func() error {
|
StressTest(func() error {
|
||||||
b.AddEventListener(events.EventLoad, func(message interface{}) {})
|
b.AddEventListener(events.EventLoad, func(ctx context.Context, message interface{}) {})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}, 500)
|
}, 500)
|
||||||
@ -222,7 +223,7 @@ func TestEventBroker(t *testing.T) {
|
|||||||
b := NewTestEventBroker()
|
b := NewTestEventBroker()
|
||||||
|
|
||||||
StressTest(func() error {
|
StressTest(func() error {
|
||||||
listener := func(message interface{}) {}
|
listener := func(ctx context.Context, message interface{}) {}
|
||||||
|
|
||||||
b.AddEventListener(events.EventLoad, listener)
|
b.AddEventListener(events.EventLoad, listener)
|
||||||
b.RemoveEventListener(events.EventLoad, listener)
|
b.RemoveEventListener(events.EventLoad, listener)
|
||||||
@ -239,7 +240,7 @@ func TestEventBroker(t *testing.T) {
|
|||||||
defer b.Stop()
|
defer b.Stop()
|
||||||
|
|
||||||
StressTest(func() error {
|
StressTest(func() error {
|
||||||
listener := func(message interface{}) {}
|
listener := func(ctx context.Context, message interface{}) {}
|
||||||
|
|
||||||
b.AddEventListener(events.EventLoad, listener)
|
b.AddEventListener(events.EventLoad, listener)
|
||||||
|
|
||||||
@ -267,7 +268,7 @@ func TestEventBroker(t *testing.T) {
|
|||||||
|
|
||||||
var listener events.EventListener
|
var listener events.EventListener
|
||||||
|
|
||||||
listener = func(message interface{}) {
|
listener = func(ctx context.Context, message interface{}) {
|
||||||
counter += 1
|
counter += 1
|
||||||
|
|
||||||
b.RemoveEventListener(events.EventLoad, listener)
|
b.RemoveEventListener(events.EventLoad, listener)
|
||||||
@ -296,7 +297,7 @@ func TestEventBroker(t *testing.T) {
|
|||||||
|
|
||||||
var counter int64
|
var counter int64
|
||||||
|
|
||||||
b.AddEventListener(events.EventLoad, func(message interface{}) {
|
b.AddEventListener(events.EventLoad, func(ctx context.Context, message interface{}) {
|
||||||
atomic.AddInt64(&counter, 1)
|
atomic.AddInt64(&counter, 1)
|
||||||
b.Stop()
|
b.Stop()
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package events
|
package events
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/MontFerret/ferret/pkg/drivers/cdp/eval"
|
"github.com/MontFerret/ferret/pkg/drivers/cdp/eval"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||||
@ -9,10 +10,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Function func() (core.Value, error)
|
Function func(ctx context.Context) (core.Value, error)
|
||||||
|
|
||||||
WaitTask struct {
|
WaitTask struct {
|
||||||
fun Function
|
fun Function
|
||||||
timeout time.Duration
|
|
||||||
polling time.Duration
|
polling time.Duration
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -21,39 +22,31 @@ const DefaultPolling = time.Millisecond * time.Duration(200)
|
|||||||
|
|
||||||
func NewWaitTask(
|
func NewWaitTask(
|
||||||
fun Function,
|
fun Function,
|
||||||
timeout time.Duration,
|
|
||||||
polling time.Duration,
|
polling time.Duration,
|
||||||
) *WaitTask {
|
) *WaitTask {
|
||||||
return &WaitTask{
|
return &WaitTask{
|
||||||
fun,
|
fun,
|
||||||
timeout,
|
|
||||||
polling,
|
polling,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (task *WaitTask) Run() (core.Value, error) {
|
func (task *WaitTask) Run(ctx context.Context) (core.Value, error) {
|
||||||
timer := time.NewTimer(task.timeout)
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-timer.C:
|
case <-ctx.Done():
|
||||||
return values.None, core.ErrTimeout
|
return values.None, core.ErrTimeout
|
||||||
default:
|
default:
|
||||||
out, err := task.fun()
|
out, err := task.fun(ctx)
|
||||||
|
|
||||||
// expression failed
|
// expression failed
|
||||||
// terminating
|
// terminating
|
||||||
if err != nil {
|
if err != nil {
|
||||||
timer.Stop()
|
|
||||||
|
|
||||||
return values.None, err
|
return values.None, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// output is not empty
|
// output is not empty
|
||||||
// terminating
|
// terminating
|
||||||
if out != values.None {
|
if out != values.None {
|
||||||
timer.Stop()
|
|
||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,19 +59,18 @@ func (task *WaitTask) Run() (core.Value, error) {
|
|||||||
func NewEvalWaitTask(
|
func NewEvalWaitTask(
|
||||||
client *cdp.Client,
|
client *cdp.Client,
|
||||||
predicate string,
|
predicate string,
|
||||||
timeout time.Duration,
|
|
||||||
polling time.Duration,
|
polling time.Duration,
|
||||||
) *WaitTask {
|
) *WaitTask {
|
||||||
return NewWaitTask(
|
return NewWaitTask(
|
||||||
func() (core.Value, error) {
|
func(ctx context.Context) (core.Value, error) {
|
||||||
return eval.Eval(
|
return eval.Eval(
|
||||||
|
ctx,
|
||||||
client,
|
client,
|
||||||
predicate,
|
predicate,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
timeout,
|
|
||||||
polling,
|
polling,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -287,10 +287,6 @@ func createChildrenArray(nodes []dom.Node) []*HTMLElementIdentity {
|
|||||||
return children
|
return children
|
||||||
}
|
}
|
||||||
|
|
||||||
func contextWithTimeout() (context.Context, context.CancelFunc) {
|
|
||||||
return context.WithTimeout(context.Background(), DefaultTimeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
func waitForLoadEvent(ctx context.Context, client *cdp.Client) error {
|
func waitForLoadEvent(ctx context.Context, client *cdp.Client) error {
|
||||||
loadEventFired, err := client.Page.LoadEventFired(ctx)
|
loadEventFired, err := client.Page.LoadEventFired(ctx)
|
||||||
|
|
||||||
|
@ -23,9 +23,9 @@ func GetInDocument(ctx context.Context, doc drivers.HTMLDocument, path []core.Va
|
|||||||
case "url", "URL":
|
case "url", "URL":
|
||||||
return doc.GetURL(), nil
|
return doc.GetURL(), nil
|
||||||
case "body":
|
case "body":
|
||||||
return doc.QuerySelector("body"), nil
|
return doc.QuerySelector(ctx, "body"), nil
|
||||||
case "head":
|
case "head":
|
||||||
return doc.QuerySelector("head"), nil
|
return doc.QuerySelector(ctx, "head"), nil
|
||||||
default:
|
default:
|
||||||
return GetInNode(ctx, doc.DocumentElement(), path)
|
return GetInNode(ctx, doc.DocumentElement(), path)
|
||||||
}
|
}
|
||||||
@ -46,13 +46,13 @@ func GetInElement(ctx context.Context, el drivers.HTMLElement, path []core.Value
|
|||||||
|
|
||||||
switch segment {
|
switch segment {
|
||||||
case "innerText":
|
case "innerText":
|
||||||
return el.InnerText(), nil
|
return el.InnerText(ctx), nil
|
||||||
case "innerHTML":
|
case "innerHTML":
|
||||||
return el.InnerHTML(), nil
|
return el.InnerHTML(ctx), nil
|
||||||
case "value":
|
case "value":
|
||||||
return el.GetValue(), nil
|
return el.GetValue(ctx), nil
|
||||||
case "attributes":
|
case "attributes":
|
||||||
return el.GetAttributes(), nil
|
return el.GetAttributes(ctx), nil
|
||||||
default:
|
default:
|
||||||
return GetInNode(ctx, el, path)
|
return GetInNode(ctx, el, path)
|
||||||
}
|
}
|
||||||
@ -74,7 +74,7 @@ func GetInNode(ctx context.Context, node drivers.HTMLNode, path []core.Value) (c
|
|||||||
if nt == drivers.HTMLElementType || nt == drivers.HTMLDocumentType {
|
if nt == drivers.HTMLElementType || nt == drivers.HTMLDocumentType {
|
||||||
re := node.(drivers.HTMLNode)
|
re := node.(drivers.HTMLNode)
|
||||||
|
|
||||||
return re.GetChildNode(segment.(values.Int)), nil
|
return re.GetChildNode(ctx, segment.(values.Int)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return values.GetIn(ctx, node, path[0:])
|
return values.GetIn(ctx, node, path[0:])
|
||||||
@ -89,7 +89,7 @@ func GetInNode(ctx context.Context, node drivers.HTMLNode, path []core.Value) (c
|
|||||||
case "nodeName":
|
case "nodeName":
|
||||||
return node.NodeName(), nil
|
return node.NodeName(), nil
|
||||||
case "children":
|
case "children":
|
||||||
return node.GetChildNodes(), nil
|
return node.GetChildNodes(ctx), nil
|
||||||
case "length":
|
case "length":
|
||||||
return node.Length(), nil
|
return node.Length(), nil
|
||||||
default:
|
default:
|
||||||
|
@ -23,10 +23,10 @@ func NewIterator(
|
|||||||
return &Iterator{node, 0}, nil
|
return &Iterator{node, 0}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iterator *Iterator) Next(_ context.Context) (value core.Value, key core.Value, err error) {
|
func (iterator *Iterator) Next(ctx context.Context) (value core.Value, key core.Value, err error) {
|
||||||
if iterator.node.Length() > iterator.pos {
|
if iterator.node.Length() > iterator.pos {
|
||||||
idx := iterator.pos
|
idx := iterator.pos
|
||||||
val := iterator.node.GetChildNode(idx)
|
val := iterator.node.GetChildNode(ctx, idx)
|
||||||
|
|
||||||
iterator.pos++
|
iterator.pos++
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||||
@ -8,7 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
LazyFactory func() (core.Value, error)
|
LazyFactory func(ctx context.Context) (core.Value, error)
|
||||||
|
|
||||||
LazyValue struct {
|
LazyValue struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
@ -40,12 +41,12 @@ func (lv *LazyValue) Ready() bool {
|
|||||||
// Read returns an underlying value.
|
// Read returns an underlying value.
|
||||||
// Not thread safe. Should not mutated.
|
// Not thread safe. Should not mutated.
|
||||||
// @returns (Value) - Underlying value if successfully loaded, otherwise error
|
// @returns (Value) - Underlying value if successfully loaded, otherwise error
|
||||||
func (lv *LazyValue) Read() (core.Value, error) {
|
func (lv *LazyValue) Read(ctx context.Context) (core.Value, error) {
|
||||||
lv.Lock()
|
lv.Lock()
|
||||||
defer lv.Unlock()
|
defer lv.Unlock()
|
||||||
|
|
||||||
if !lv.ready {
|
if !lv.ready {
|
||||||
lv.load()
|
lv.load(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
return lv.value, lv.err
|
return lv.value, lv.err
|
||||||
@ -54,12 +55,12 @@ func (lv *LazyValue) Read() (core.Value, error) {
|
|||||||
// Write safely mutates an underlying value.
|
// Write safely mutates an underlying value.
|
||||||
// Loads a value if it's not ready.
|
// Loads a value if it's not ready.
|
||||||
// Thread safe.
|
// Thread safe.
|
||||||
func (lv *LazyValue) Write(writer func(v core.Value, err error)) {
|
func (lv *LazyValue) Write(ctx context.Context, writer func(v core.Value, err error)) {
|
||||||
lv.Lock()
|
lv.Lock()
|
||||||
defer lv.Unlock()
|
defer lv.Unlock()
|
||||||
|
|
||||||
if !lv.ready {
|
if !lv.ready {
|
||||||
lv.load()
|
lv.load(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
writer(lv.value, lv.err)
|
writer(lv.value, lv.err)
|
||||||
@ -76,8 +77,8 @@ func (lv *LazyValue) Reset() {
|
|||||||
lv.err = nil
|
lv.err = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lv *LazyValue) load() {
|
func (lv *LazyValue) load(ctx context.Context) {
|
||||||
val, err := lv.factory()
|
val, err := lv.factory(ctx)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
lv.value = val
|
lv.value = val
|
||||||
|
@ -21,7 +21,7 @@ func SetInDocument(ctx context.Context, doc drivers.HTMLDocument, path []core.Va
|
|||||||
|
|
||||||
switch segment {
|
switch segment {
|
||||||
case "url", "URL":
|
case "url", "URL":
|
||||||
return doc.SetURL(values.NewString(value.String()))
|
return doc.SetURL(ctx, values.NewString(value.String()))
|
||||||
default:
|
default:
|
||||||
return SetInNode(ctx, doc, path, value)
|
return SetInNode(ctx, doc, path, value)
|
||||||
}
|
}
|
||||||
@ -45,7 +45,7 @@ func SetInElement(ctx context.Context, el drivers.HTMLElement, path []core.Value
|
|||||||
if len(path) > 1 {
|
if len(path) > 1 {
|
||||||
attrName := path[1]
|
attrName := path[1]
|
||||||
|
|
||||||
return el.SetAttribute(values.NewString(attrName.String()), values.NewString(value.String()))
|
return el.SetAttribute(ctx, values.NewString(attrName.String()), values.NewString(value.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
err := core.ValidateType(value, types.Object)
|
err := core.ValidateType(value, types.Object)
|
||||||
@ -56,7 +56,7 @@ func SetInElement(ctx context.Context, el drivers.HTMLElement, path []core.Value
|
|||||||
|
|
||||||
obj := value.(*values.Object)
|
obj := value.(*values.Object)
|
||||||
obj.ForEach(func(value core.Value, key string) bool {
|
obj.ForEach(func(value core.Value, key string) bool {
|
||||||
err = el.SetAttribute(values.NewString(key), values.NewString(value.String()))
|
err = el.SetAttribute(ctx, values.NewString(key), values.NewString(value.String()))
|
||||||
|
|
||||||
return err == nil
|
return err == nil
|
||||||
})
|
})
|
||||||
@ -67,7 +67,7 @@ func SetInElement(ctx context.Context, el drivers.HTMLElement, path []core.Value
|
|||||||
return core.Error(ErrInvalidPath, PathToString(path[1:]))
|
return core.Error(ErrInvalidPath, PathToString(path[1:]))
|
||||||
}
|
}
|
||||||
|
|
||||||
return el.SetValue(value)
|
return el.SetValue(ctx, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,11 +3,14 @@ package drivers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const DefaultTimeout = time.Second * 30
|
||||||
|
|
||||||
type (
|
type (
|
||||||
ctxKey struct{}
|
ctxKey struct{}
|
||||||
|
|
||||||
|
9
pkg/drivers/helpers.go
Normal file
9
pkg/drivers/helpers.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package drivers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WithDefaultTimeout(ctx context.Context) (context.Context, context.CancelFunc) {
|
||||||
|
return context.WithTimeout(ctx, DefaultTimeout)
|
||||||
|
}
|
@ -125,28 +125,28 @@ func (doc *HTMLDocument) NodeName() values.String {
|
|||||||
return "#document"
|
return "#document"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) GetChildNodes() core.Value {
|
func (doc *HTMLDocument) GetChildNodes(ctx context.Context) core.Value {
|
||||||
return doc.element.GetChildNodes()
|
return doc.element.GetChildNodes(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) GetChildNode(idx values.Int) core.Value {
|
func (doc *HTMLDocument) GetChildNode(ctx context.Context, idx values.Int) core.Value {
|
||||||
return doc.element.GetChildNode(idx)
|
return doc.element.GetChildNode(ctx, idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) QuerySelector(selector values.String) core.Value {
|
func (doc *HTMLDocument) QuerySelector(ctx context.Context, selector values.String) core.Value {
|
||||||
return doc.element.QuerySelector(selector)
|
return doc.element.QuerySelector(ctx, selector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) QuerySelectorAll(selector values.String) core.Value {
|
func (doc *HTMLDocument) QuerySelectorAll(ctx context.Context, selector values.String) core.Value {
|
||||||
return doc.element.QuerySelectorAll(selector)
|
return doc.element.QuerySelectorAll(ctx, selector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) CountBySelector(selector values.String) values.Int {
|
func (doc *HTMLDocument) CountBySelector(ctx context.Context, selector values.String) values.Int {
|
||||||
return doc.element.CountBySelector(selector)
|
return doc.element.CountBySelector(ctx, selector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) ExistsBySelector(selector values.String) values.Boolean {
|
func (doc *HTMLDocument) ExistsBySelector(ctx context.Context, selector values.String) values.Boolean {
|
||||||
return doc.element.ExistsBySelector(selector)
|
return doc.element.ExistsBySelector(ctx, selector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) DocumentElement() drivers.HTMLElement {
|
func (doc *HTMLDocument) DocumentElement() drivers.HTMLElement {
|
||||||
@ -157,75 +157,75 @@ func (doc *HTMLDocument) GetURL() core.Value {
|
|||||||
return doc.url
|
return doc.url
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) SetURL(_ values.String) error {
|
func (doc *HTMLDocument) SetURL(_ context.Context, _ values.String) error {
|
||||||
return core.ErrInvalidOperation
|
return core.ErrInvalidOperation
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) Navigate(_ values.String, _ values.Int) error {
|
func (doc *HTMLDocument) Navigate(_ context.Context, _ values.String) error {
|
||||||
return core.ErrNotSupported
|
return core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) NavigateBack(_ values.Int, _ values.Int) (values.Boolean, error) {
|
func (doc *HTMLDocument) NavigateBack(_ context.Context, _ values.Int) (values.Boolean, error) {
|
||||||
return false, core.ErrNotSupported
|
return false, core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) NavigateForward(_ values.Int, _ values.Int) (values.Boolean, error) {
|
func (doc *HTMLDocument) NavigateForward(_ context.Context, _ values.Int) (values.Boolean, error) {
|
||||||
return false, core.ErrNotSupported
|
return false, core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) ClickBySelector(_ values.String) (values.Boolean, error) {
|
func (doc *HTMLDocument) ClickBySelector(_ context.Context, _ values.String) (values.Boolean, error) {
|
||||||
return false, core.ErrNotSupported
|
return false, core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) ClickBySelectorAll(_ values.String) (values.Boolean, error) {
|
func (doc *HTMLDocument) ClickBySelectorAll(_ context.Context, _ values.String) (values.Boolean, error) {
|
||||||
return false, core.ErrNotSupported
|
return false, core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) InputBySelector(_ values.String, _ core.Value, _ values.Int) (values.Boolean, error) {
|
func (doc *HTMLDocument) InputBySelector(_ context.Context, _ values.String, _ core.Value, _ values.Int) (values.Boolean, error) {
|
||||||
return false, core.ErrNotSupported
|
return false, core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) SelectBySelector(_ values.String, _ *values.Array) (*values.Array, error) {
|
func (doc *HTMLDocument) SelectBySelector(_ context.Context, _ values.String, _ *values.Array) (*values.Array, error) {
|
||||||
return nil, core.ErrNotSupported
|
return nil, core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) HoverBySelector(_ values.String) error {
|
func (doc *HTMLDocument) HoverBySelector(_ context.Context, _ values.String) error {
|
||||||
return core.ErrNotSupported
|
return core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) PrintToPDF(_ drivers.PDFParams) (values.Binary, error) {
|
func (doc *HTMLDocument) PrintToPDF(_ context.Context, _ drivers.PDFParams) (values.Binary, error) {
|
||||||
return nil, core.ErrNotSupported
|
return nil, core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) CaptureScreenshot(_ drivers.ScreenshotParams) (values.Binary, error) {
|
func (doc *HTMLDocument) CaptureScreenshot(_ context.Context, _ drivers.ScreenshotParams) (values.Binary, error) {
|
||||||
return nil, core.ErrNotSupported
|
return nil, core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) ScrollTop() error {
|
func (doc *HTMLDocument) ScrollTop(_ context.Context) error {
|
||||||
return core.ErrNotSupported
|
return core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) ScrollBottom() error {
|
func (doc *HTMLDocument) ScrollBottom(_ context.Context) error {
|
||||||
return core.ErrNotSupported
|
return core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) ScrollBySelector(_ values.String) error {
|
func (doc *HTMLDocument) ScrollBySelector(_ context.Context, _ values.String) error {
|
||||||
return core.ErrNotSupported
|
return core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) WaitForNavigation(_ values.Int) error {
|
func (doc *HTMLDocument) WaitForNavigation(_ context.Context) error {
|
||||||
return core.ErrNotSupported
|
return core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) WaitForSelector(_ values.String, _ values.Int) error {
|
func (doc *HTMLDocument) WaitForSelector(_ context.Context, _ values.String) error {
|
||||||
return core.ErrNotSupported
|
return core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) WaitForClassBySelector(_, _ values.String, _ values.Int) error {
|
func (doc *HTMLDocument) WaitForClassBySelector(_ context.Context, _, _ values.String) error {
|
||||||
return core.ErrNotSupported
|
return core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *HTMLDocument) WaitForClassBySelectorAll(_, _ values.String, _ values.Int) error {
|
func (doc *HTMLDocument) WaitForClassBySelectorAll(_ context.Context, _, _ values.String) error {
|
||||||
return core.ErrNotSupported
|
return core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ func NewHTMLElement(node *goquery.Selection) (drivers.HTMLElement, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) MarshalJSON() ([]byte, error) {
|
func (nd *HTMLElement) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(nd.InnerText().String())
|
return json.Marshal(nd.InnerText(context.Background()).String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) Type() core.Type {
|
func (nd *HTMLElement) Type() core.Type {
|
||||||
@ -35,7 +35,7 @@ func (nd *HTMLElement) Type() core.Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) String() string {
|
func (nd *HTMLElement) String() string {
|
||||||
return nd.InnerHTML().String()
|
return nd.InnerHTML(context.Background()).String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) Compare(other core.Value) int64 {
|
func (nd *HTMLElement) Compare(other core.Value) int64 {
|
||||||
@ -43,7 +43,10 @@ func (nd *HTMLElement) Compare(other core.Value) int64 {
|
|||||||
case drivers.HTMLElementType:
|
case drivers.HTMLElementType:
|
||||||
other := other.(drivers.HTMLElement)
|
other := other.(drivers.HTMLElement)
|
||||||
|
|
||||||
return nd.InnerHTML().Compare(other.InnerHTML())
|
ctx, fn := drivers.WithDefaultTimeout(context.Background())
|
||||||
|
defer fn()
|
||||||
|
|
||||||
|
return nd.InnerHTML(ctx).Compare(other.InnerHTML(ctx))
|
||||||
default:
|
default:
|
||||||
return drivers.Compare(nd.Type(), other.Type())
|
return drivers.Compare(nd.Type(), other.Type())
|
||||||
}
|
}
|
||||||
@ -101,7 +104,7 @@ func (nd *HTMLElement) Length() values.Int {
|
|||||||
return nd.children.Length()
|
return nd.children.Length()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) GetValue() core.Value {
|
func (nd *HTMLElement) GetValue(_ context.Context) core.Value {
|
||||||
val, ok := nd.selection.Attr("value")
|
val, ok := nd.selection.Attr("value")
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
@ -111,17 +114,17 @@ func (nd *HTMLElement) GetValue() core.Value {
|
|||||||
return values.EmptyString
|
return values.EmptyString
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) SetValue(value core.Value) error {
|
func (nd *HTMLElement) SetValue(_ context.Context, value core.Value) error {
|
||||||
nd.selection.SetAttr("value", value.String())
|
nd.selection.SetAttr("value", value.String())
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) InnerText() values.String {
|
func (nd *HTMLElement) InnerText(_ context.Context) values.String {
|
||||||
return values.NewString(nd.selection.Text())
|
return values.NewString(nd.selection.Text())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) InnerHTML() values.String {
|
func (nd *HTMLElement) InnerHTML(_ context.Context) values.String {
|
||||||
h, err := nd.selection.Html()
|
h, err := nd.selection.Html()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -131,7 +134,7 @@ func (nd *HTMLElement) InnerHTML() values.String {
|
|||||||
return values.NewString(h)
|
return values.NewString(h)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) GetAttributes() core.Value {
|
func (nd *HTMLElement) GetAttributes(_ context.Context) core.Value {
|
||||||
if nd.attrs == nil {
|
if nd.attrs == nil {
|
||||||
nd.attrs = nd.parseAttrs()
|
nd.attrs = nd.parseAttrs()
|
||||||
}
|
}
|
||||||
@ -139,7 +142,7 @@ func (nd *HTMLElement) GetAttributes() core.Value {
|
|||||||
return nd.attrs
|
return nd.attrs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) GetAttribute(name values.String) core.Value {
|
func (nd *HTMLElement) GetAttribute(_ context.Context, name values.String) core.Value {
|
||||||
v, ok := nd.selection.Attr(name.String())
|
v, ok := nd.selection.Attr(name.String())
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
@ -149,13 +152,13 @@ func (nd *HTMLElement) GetAttribute(name values.String) core.Value {
|
|||||||
return values.None
|
return values.None
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) SetAttribute(name, value values.String) error {
|
func (nd *HTMLElement) SetAttribute(_ context.Context, name, value values.String) error {
|
||||||
nd.selection.SetAttr(string(name), string(value))
|
nd.selection.SetAttr(string(name), string(value))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) GetChildNodes() core.Value {
|
func (nd *HTMLElement) GetChildNodes(_ context.Context) core.Value {
|
||||||
if nd.children == nil {
|
if nd.children == nil {
|
||||||
nd.children = nd.parseChildren()
|
nd.children = nd.parseChildren()
|
||||||
}
|
}
|
||||||
@ -163,7 +166,7 @@ func (nd *HTMLElement) GetChildNodes() core.Value {
|
|||||||
return nd.children
|
return nd.children
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) GetChildNode(idx values.Int) core.Value {
|
func (nd *HTMLElement) GetChildNode(_ context.Context, idx values.Int) core.Value {
|
||||||
if nd.children == nil {
|
if nd.children == nil {
|
||||||
nd.children = nd.parseChildren()
|
nd.children = nd.parseChildren()
|
||||||
}
|
}
|
||||||
@ -171,7 +174,7 @@ func (nd *HTMLElement) GetChildNode(idx values.Int) core.Value {
|
|||||||
return nd.children.Get(idx)
|
return nd.children.Get(idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) QuerySelector(selector values.String) core.Value {
|
func (nd *HTMLElement) QuerySelector(_ context.Context, selector values.String) core.Value {
|
||||||
selection := nd.selection.Find(selector.String())
|
selection := nd.selection.Find(selector.String())
|
||||||
|
|
||||||
if selection == nil {
|
if selection == nil {
|
||||||
@ -187,7 +190,7 @@ func (nd *HTMLElement) QuerySelector(selector values.String) core.Value {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) QuerySelectorAll(selector values.String) core.Value {
|
func (nd *HTMLElement) QuerySelectorAll(_ context.Context, selector values.String) core.Value {
|
||||||
selection := nd.selection.Find(selector.String())
|
selection := nd.selection.Find(selector.String())
|
||||||
|
|
||||||
if selection == nil {
|
if selection == nil {
|
||||||
@ -207,7 +210,7 @@ func (nd *HTMLElement) QuerySelectorAll(selector values.String) core.Value {
|
|||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) InnerHTMLBySelector(selector values.String) values.String {
|
func (nd *HTMLElement) InnerHTMLBySelector(_ context.Context, selector values.String) values.String {
|
||||||
selection := nd.selection.Find(selector.String())
|
selection := nd.selection.Find(selector.String())
|
||||||
|
|
||||||
str, err := selection.Html()
|
str, err := selection.Html()
|
||||||
@ -220,7 +223,7 @@ func (nd *HTMLElement) InnerHTMLBySelector(selector values.String) values.String
|
|||||||
return values.NewString(str)
|
return values.NewString(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) InnerHTMLBySelectorAll(selector values.String) *values.Array {
|
func (nd *HTMLElement) InnerHTMLBySelectorAll(_ context.Context, selector values.String) *values.Array {
|
||||||
selection := nd.selection.Find(selector.String())
|
selection := nd.selection.Find(selector.String())
|
||||||
arr := values.NewArray(selection.Length())
|
arr := values.NewArray(selection.Length())
|
||||||
|
|
||||||
@ -236,13 +239,13 @@ func (nd *HTMLElement) InnerHTMLBySelectorAll(selector values.String) *values.Ar
|
|||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) InnerTextBySelector(selector values.String) values.String {
|
func (nd *HTMLElement) InnerTextBySelector(_ context.Context, selector values.String) values.String {
|
||||||
selection := nd.selection.Find(selector.String())
|
selection := nd.selection.Find(selector.String())
|
||||||
|
|
||||||
return values.NewString(selection.Text())
|
return values.NewString(selection.Text())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) InnerTextBySelectorAll(selector values.String) *values.Array {
|
func (nd *HTMLElement) InnerTextBySelectorAll(_ context.Context, selector values.String) *values.Array {
|
||||||
selection := nd.selection.Find(selector.String())
|
selection := nd.selection.Find(selector.String())
|
||||||
arr := values.NewArray(selection.Length())
|
arr := values.NewArray(selection.Length())
|
||||||
|
|
||||||
@ -253,7 +256,7 @@ func (nd *HTMLElement) InnerTextBySelectorAll(selector values.String) *values.Ar
|
|||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) CountBySelector(selector values.String) values.Int {
|
func (nd *HTMLElement) CountBySelector(_ context.Context, selector values.String) values.Int {
|
||||||
selection := nd.selection.Find(selector.String())
|
selection := nd.selection.Find(selector.String())
|
||||||
|
|
||||||
if selection == nil {
|
if selection == nil {
|
||||||
@ -263,7 +266,7 @@ func (nd *HTMLElement) CountBySelector(selector values.String) values.Int {
|
|||||||
return values.NewInt(selection.Size())
|
return values.NewInt(selection.Size())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) ExistsBySelector(selector values.String) values.Boolean {
|
func (nd *HTMLElement) ExistsBySelector(_ context.Context, selector values.String) values.Boolean {
|
||||||
selection := nd.selection.Closest(selector.String())
|
selection := nd.selection.Closest(selector.String())
|
||||||
|
|
||||||
if selection == nil {
|
if selection == nil {
|
||||||
@ -285,27 +288,27 @@ func (nd *HTMLElement) Iterate(_ context.Context) (core.Iterator, error) {
|
|||||||
return common.NewIterator(nd)
|
return common.NewIterator(nd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) Click() (values.Boolean, error) {
|
func (nd *HTMLElement) Click(_ context.Context) (values.Boolean, error) {
|
||||||
return false, core.ErrNotSupported
|
return false, core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) Input(_ core.Value, _ values.Int) error {
|
func (nd *HTMLElement) Input(_ context.Context, _ core.Value, _ values.Int) error {
|
||||||
return core.ErrNotSupported
|
return core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) Select(_ *values.Array) (*values.Array, error) {
|
func (nd *HTMLElement) Select(_ context.Context, _ *values.Array) (*values.Array, error) {
|
||||||
return nil, core.ErrNotSupported
|
return nil, core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) ScrollIntoView() error {
|
func (nd *HTMLElement) ScrollIntoView(_ context.Context) error {
|
||||||
return core.ErrNotSupported
|
return core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) Hover() error {
|
func (nd *HTMLElement) Hover(_ context.Context) error {
|
||||||
return core.ErrNotSupported
|
return core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *HTMLElement) WaitForClass(_ values.String, _ values.Int) error {
|
func (nd *HTMLElement) WaitForClass(_ context.Context, _ values.String) error {
|
||||||
return core.ErrNotSupported
|
return core.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package http_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"github.com/MontFerret/ferret/pkg/drivers"
|
"github.com/MontFerret/ferret/pkg/drivers"
|
||||||
"github.com/MontFerret/ferret/pkg/drivers/http"
|
"github.com/MontFerret/ferret/pkg/drivers/http"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||||
@ -321,7 +322,7 @@ func TestElement(t *testing.T) {
|
|||||||
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
v := el.GetValue()
|
v := el.GetValue(context.Background())
|
||||||
|
|
||||||
So(v, ShouldEqual, "find")
|
So(v, ShouldEqual, "find")
|
||||||
})
|
})
|
||||||
@ -348,7 +349,7 @@ func TestElement(t *testing.T) {
|
|||||||
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
v := el.InnerText()
|
v := el.InnerText(context.Background())
|
||||||
|
|
||||||
So(v, ShouldEqual, "Ferret")
|
So(v, ShouldEqual, "Ferret")
|
||||||
})
|
})
|
||||||
@ -375,7 +376,7 @@ func TestElement(t *testing.T) {
|
|||||||
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
v := el.InnerHTML()
|
v := el.InnerHTML(context.Background())
|
||||||
|
|
||||||
So(v, ShouldEqual, "<h2>Ferret</h2>")
|
So(v, ShouldEqual, "<h2>Ferret</h2>")
|
||||||
})
|
})
|
||||||
@ -391,7 +392,7 @@ func TestElement(t *testing.T) {
|
|||||||
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
found := el.QuerySelector(values.NewString("body .card-img-top:nth-child(1)"))
|
found := el.QuerySelector(context.Background(), values.NewString("body .card-img-top:nth-child(1)"))
|
||||||
|
|
||||||
So(found, ShouldNotEqual, values.None)
|
So(found, ShouldNotEqual, values.None)
|
||||||
|
|
||||||
@ -413,7 +414,7 @@ func TestElement(t *testing.T) {
|
|||||||
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
v := el.CountBySelector(values.NewString("head meta"))
|
v := el.CountBySelector(context.Background(), values.NewString("head meta"))
|
||||||
|
|
||||||
So(v, ShouldEqual, 4)
|
So(v, ShouldEqual, 4)
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package drivers
|
package drivers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/collections"
|
"github.com/MontFerret/ferret/pkg/runtime/collections"
|
||||||
@ -24,56 +25,56 @@ type (
|
|||||||
|
|
||||||
NodeName() values.String
|
NodeName() values.String
|
||||||
|
|
||||||
GetChildNodes() core.Value
|
GetChildNodes(ctx context.Context) core.Value
|
||||||
|
|
||||||
GetChildNode(idx values.Int) core.Value
|
GetChildNode(ctx context.Context, idx values.Int) core.Value
|
||||||
|
|
||||||
QuerySelector(selector values.String) core.Value
|
QuerySelector(ctx context.Context, selector values.String) core.Value
|
||||||
|
|
||||||
QuerySelectorAll(selector values.String) core.Value
|
QuerySelectorAll(ctx context.Context, selector values.String) core.Value
|
||||||
|
|
||||||
CountBySelector(selector values.String) values.Int
|
CountBySelector(ctx context.Context, selector values.String) values.Int
|
||||||
|
|
||||||
ExistsBySelector(selector values.String) values.Boolean
|
ExistsBySelector(ctx context.Context, selector values.String) values.Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTMLElement is the most general base interface which most objects in a Document implement.
|
// HTMLElement is the most general base interface which most objects in a Document implement.
|
||||||
HTMLElement interface {
|
HTMLElement interface {
|
||||||
HTMLNode
|
HTMLNode
|
||||||
|
|
||||||
InnerText() values.String
|
InnerText(ctx context.Context) values.String
|
||||||
|
|
||||||
InnerHTML() values.String
|
InnerHTML(ctx context.Context) values.String
|
||||||
|
|
||||||
GetValue() core.Value
|
GetValue(ctx context.Context) core.Value
|
||||||
|
|
||||||
SetValue(value core.Value) error
|
SetValue(ctx context.Context, value core.Value) error
|
||||||
|
|
||||||
GetAttributes() core.Value
|
GetAttributes(ctx context.Context) core.Value
|
||||||
|
|
||||||
GetAttribute(name values.String) core.Value
|
GetAttribute(ctx context.Context, name values.String) core.Value
|
||||||
|
|
||||||
SetAttribute(name, value values.String) error
|
SetAttribute(ctx context.Context, name, value values.String) error
|
||||||
|
|
||||||
InnerHTMLBySelector(selector values.String) values.String
|
InnerHTMLBySelector(ctx context.Context, selector values.String) values.String
|
||||||
|
|
||||||
InnerHTMLBySelectorAll(selector values.String) *values.Array
|
InnerHTMLBySelectorAll(ctx context.Context, selector values.String) *values.Array
|
||||||
|
|
||||||
InnerTextBySelector(selector values.String) values.String
|
InnerTextBySelector(ctx context.Context, selector values.String) values.String
|
||||||
|
|
||||||
InnerTextBySelectorAll(selector values.String) *values.Array
|
InnerTextBySelectorAll(ctx context.Context, selector values.String) *values.Array
|
||||||
|
|
||||||
Click() (values.Boolean, error)
|
Click(ctx context.Context) (values.Boolean, error)
|
||||||
|
|
||||||
Input(value core.Value, delay values.Int) error
|
Input(ctx context.Context, value core.Value, delay values.Int) error
|
||||||
|
|
||||||
Select(value *values.Array) (*values.Array, error)
|
Select(ctx context.Context, value *values.Array) (*values.Array, error)
|
||||||
|
|
||||||
ScrollIntoView() error
|
ScrollIntoView(ctx context.Context) error
|
||||||
|
|
||||||
Hover() error
|
Hover(ctx context.Context) error
|
||||||
|
|
||||||
WaitForClass(class values.String, timeout values.Int) error
|
WaitForClass(ctx context.Context, class values.String) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Document interface represents any web page loaded in the browser
|
// The Document interface represents any web page loaded in the browser
|
||||||
@ -85,40 +86,40 @@ type (
|
|||||||
|
|
||||||
GetURL() core.Value
|
GetURL() core.Value
|
||||||
|
|
||||||
SetURL(url values.String) error
|
SetURL(ctx context.Context, url values.String) error
|
||||||
|
|
||||||
Navigate(url values.String, timeout values.Int) error
|
Navigate(ctx context.Context, url values.String) error
|
||||||
|
|
||||||
NavigateBack(skip values.Int, timeout values.Int) (values.Boolean, error)
|
NavigateBack(ctx context.Context, skip values.Int) (values.Boolean, error)
|
||||||
|
|
||||||
NavigateForward(skip values.Int, timeout values.Int) (values.Boolean, error)
|
NavigateForward(ctx context.Context, skip values.Int) (values.Boolean, error)
|
||||||
|
|
||||||
ClickBySelector(selector values.String) (values.Boolean, error)
|
ClickBySelector(ctx context.Context, selector values.String) (values.Boolean, error)
|
||||||
|
|
||||||
ClickBySelectorAll(selector values.String) (values.Boolean, error)
|
ClickBySelectorAll(ctx context.Context, selector values.String) (values.Boolean, error)
|
||||||
|
|
||||||
InputBySelector(selector values.String, value core.Value, delay values.Int) (values.Boolean, error)
|
InputBySelector(ctx context.Context, selector values.String, value core.Value, delay values.Int) (values.Boolean, error)
|
||||||
|
|
||||||
SelectBySelector(selector values.String, value *values.Array) (*values.Array, error)
|
SelectBySelector(ctx context.Context, selector values.String, value *values.Array) (*values.Array, error)
|
||||||
|
|
||||||
HoverBySelector(selector values.String) error
|
HoverBySelector(ctx context.Context, selector values.String) error
|
||||||
|
|
||||||
PrintToPDF(params PDFParams) (values.Binary, error)
|
PrintToPDF(ctx context.Context, params PDFParams) (values.Binary, error)
|
||||||
|
|
||||||
CaptureScreenshot(params ScreenshotParams) (values.Binary, error)
|
CaptureScreenshot(ctx context.Context, params ScreenshotParams) (values.Binary, error)
|
||||||
|
|
||||||
ScrollTop() error
|
ScrollTop(ctx context.Context) error
|
||||||
|
|
||||||
ScrollBottom() error
|
ScrollBottom(ctx context.Context) error
|
||||||
|
|
||||||
ScrollBySelector(selector values.String) error
|
ScrollBySelector(ctx context.Context, selector values.String) error
|
||||||
|
|
||||||
WaitForNavigation(timeout values.Int) error
|
WaitForNavigation(ctx context.Context) error
|
||||||
|
|
||||||
WaitForSelector(selector values.String, timeout values.Int) error
|
WaitForSelector(ctx context.Context, selector values.String) error
|
||||||
|
|
||||||
WaitForClassBySelector(selector, class values.String, timeout values.Int) error
|
WaitForClassBySelector(ctx context.Context, selector, class values.String) error
|
||||||
|
|
||||||
WaitForClassBySelectorAll(selector, class values.String, timeout values.Int) error
|
WaitForClassBySelectorAll(ctx context.Context, selector, class values.String) error
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
// Click dispatches click event on a given element
|
// Click dispatches click event on a given element
|
||||||
// @param source (Document | Element) - Event source.
|
// @param source (Document | Element) - Event source.
|
||||||
// @param selector (String, optional) - Optional selector. Only used when a document instance is passed.
|
// @param selector (String, optional) - Optional selector. Only used when a document instance is passed.
|
||||||
func Click(_ context.Context, args ...core.Value) (core.Value, error) {
|
func Click(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
err := core.ValidateArgs(args, 1, 2)
|
err := core.ValidateArgs(args, 1, 2)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -25,7 +25,7 @@ func Click(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
return values.False, err
|
return values.False, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return el.Click()
|
return el.Click(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CLICK(doc, selector)
|
// CLICK(doc, selector)
|
||||||
@ -37,5 +37,5 @@ func Click(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
|
|
||||||
selector := args[1].String()
|
selector := args[1].String()
|
||||||
|
|
||||||
return doc.ClickBySelector(values.NewString(selector))
|
return doc.ClickBySelector(ctx, values.NewString(selector))
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
// @param source (Document) - Document.
|
// @param source (Document) - Document.
|
||||||
// @param selector (String) - Selector.
|
// @param selector (String) - Selector.
|
||||||
// @returns (Boolean) - Returns true if matched at least one element.
|
// @returns (Boolean) - Returns true if matched at least one element.
|
||||||
func ClickAll(_ context.Context, args ...core.Value) (core.Value, error) {
|
func ClickAll(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
err := core.ValidateArgs(args, 2, 2)
|
err := core.ValidateArgs(args, 2, 2)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -34,5 +34,5 @@ func ClickAll(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
return values.None, err
|
return values.None, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return doc.ClickBySelectorAll(values.NewString(selector))
|
return doc.ClickBySelectorAll(ctx, values.NewString(selector))
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,14 @@ import (
|
|||||||
// @param docOrEl (HTMLDocument|HTMLElement) - Parent document or element.
|
// @param docOrEl (HTMLDocument|HTMLElement) - Parent document or element.
|
||||||
// @param selector (String) - CSS selector.
|
// @param selector (String) - CSS selector.
|
||||||
// @returns (HTMLElement | None) - Returns an HTMLElement if found, otherwise NONE.
|
// @returns (HTMLElement | None) - Returns an HTMLElement if found, otherwise NONE.
|
||||||
func Element(_ context.Context, args ...core.Value) (core.Value, error) {
|
func Element(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
el, selector, err := queryArgs(args)
|
el, selector, err := queryArgs(args)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return values.None, err
|
return values.None, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return el.QuerySelector(selector), nil
|
return el.QuerySelector(ctx, selector), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func queryArgs(args []core.Value) (drivers.HTMLNode, values.String, error) {
|
func queryArgs(args []core.Value) (drivers.HTMLNode, values.String, error) {
|
||||||
|
@ -11,12 +11,12 @@ import (
|
|||||||
// @param docOrEl (HTMLDocument|HTMLNode) - Parent document or element.
|
// @param docOrEl (HTMLDocument|HTMLNode) - Parent document or element.
|
||||||
// @param selector (String) - CSS selector.
|
// @param selector (String) - CSS selector.
|
||||||
// @returns (Boolean) - A boolean value indicating whether there is an element matched by selector.
|
// @returns (Boolean) - A boolean value indicating whether there is an element matched by selector.
|
||||||
func ElementExists(_ context.Context, args ...core.Value) (core.Value, error) {
|
func ElementExists(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
el, selector, err := queryArgs(args)
|
el, selector, err := queryArgs(args)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return values.None, err
|
return values.None, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return el.ExistsBySelector(selector), nil
|
return el.ExistsBySelector(ctx, selector), nil
|
||||||
}
|
}
|
||||||
|
@ -12,12 +12,12 @@ import (
|
|||||||
// @param docOrEl (HTMLDocument|HTMLNode) - Parent document or element.
|
// @param docOrEl (HTMLDocument|HTMLNode) - Parent document or element.
|
||||||
// @param selector (String) - CSS selector.
|
// @param selector (String) - CSS selector.
|
||||||
// @returns (Array) - Returns an array of found HTML element.
|
// @returns (Array) - Returns an array of found HTML element.
|
||||||
func Elements(_ context.Context, args ...core.Value) (core.Value, error) {
|
func Elements(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
el, selector, err := queryArgs(args)
|
el, selector, err := queryArgs(args)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return values.None, err
|
return values.None, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return el.QuerySelectorAll(selector), nil
|
return el.QuerySelectorAll(ctx, selector), nil
|
||||||
}
|
}
|
||||||
|
@ -12,12 +12,12 @@ import (
|
|||||||
// @param docOrEl (HTMLDocument|HTMLNode) - Parent document or element.
|
// @param docOrEl (HTMLDocument|HTMLNode) - Parent document or element.
|
||||||
// @param selector (String) - CSS selector.
|
// @param selector (String) - CSS selector.
|
||||||
// @returns (Int) - A number of found HTML elements by a given CSS selector.
|
// @returns (Int) - A number of found HTML elements by a given CSS selector.
|
||||||
func ElementsCount(_ context.Context, args ...core.Value) (core.Value, error) {
|
func ElementsCount(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
el, selector, err := queryArgs(args)
|
el, selector, err := queryArgs(args)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return values.None, err
|
return values.None, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return el.CountBySelector(selector), nil
|
return el.CountBySelector(ctx, selector), nil
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
// If there's no element matching selector, the method returns an error.
|
// If there's no element matching selector, the method returns an error.
|
||||||
// @param docOrEl (HTMLDocument|HTMLElement) - Target document or element.
|
// @param docOrEl (HTMLDocument|HTMLElement) - Target document or element.
|
||||||
// @param selector (String, options) - If document is passed, this param must represent an element selector.
|
// @param selector (String, options) - If document is passed, this param must represent an element selector.
|
||||||
func Hover(_ context.Context, args ...core.Value) (core.Value, error) {
|
func Hover(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
err := core.ValidateArgs(args, 1, 2)
|
err := core.ValidateArgs(args, 1, 2)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -38,11 +38,11 @@ func Hover(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
doc := args[0].(drivers.HTMLDocument)
|
doc := args[0].(drivers.HTMLDocument)
|
||||||
selector := args[1].(values.String)
|
selector := args[1].(values.String)
|
||||||
|
|
||||||
return values.None, doc.HoverBySelector(selector)
|
return values.None, doc.HoverBySelector(ctx, selector)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Element
|
// Element
|
||||||
el := args[0].(drivers.HTMLElement)
|
el := args[0].(drivers.HTMLElement)
|
||||||
|
|
||||||
return values.None, el.Hover()
|
return values.None, el.Hover(ctx)
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
// @param doc (Document|Element) - Parent document or element.
|
// @param doc (Document|Element) - Parent document or element.
|
||||||
// @param selector (String, optional) - String of CSS selector.
|
// @param selector (String, optional) - String of CSS selector.
|
||||||
// @returns (String) - Inner HTML string if an element found, otherwise empty string.
|
// @returns (String) - Inner HTML string if an element found, otherwise empty string.
|
||||||
func InnerHTML(_ context.Context, args ...core.Value) (core.Value, error) {
|
func InnerHTML(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
err := core.ValidateArgs(args, 1, 2)
|
err := core.ValidateArgs(args, 1, 2)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -33,7 +33,7 @@ func InnerHTML(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
return el.InnerHTML(), nil
|
return el.InnerHTML(ctx), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err = core.ValidateType(args[1], types.String)
|
err = core.ValidateType(args[1], types.String)
|
||||||
@ -44,5 +44,5 @@ func InnerHTML(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
|
|
||||||
selector := args[1].(values.String)
|
selector := args[1].(values.String)
|
||||||
|
|
||||||
return el.InnerHTMLBySelector(selector), nil
|
return el.InnerHTMLBySelector(ctx, selector), nil
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
// @param doc (HTMLDocument|HTMLElement) - Parent document or element.
|
// @param doc (HTMLDocument|HTMLElement) - Parent document or element.
|
||||||
// @param selector (String) - String of CSS selector.
|
// @param selector (String) - String of CSS selector.
|
||||||
// @returns (String) - An array of inner HTML strings if any element found, otherwise empty array.
|
// @returns (String) - An array of inner HTML strings if any element found, otherwise empty array.
|
||||||
func InnerHTMLAll(_ context.Context, args ...core.Value) (core.Value, error) {
|
func InnerHTMLAll(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
err := core.ValidateArgs(args, 2, 2)
|
err := core.ValidateArgs(args, 2, 2)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -40,5 +40,5 @@ func InnerHTMLAll(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
|
|
||||||
selector := args[1].(values.String)
|
selector := args[1].(values.String)
|
||||||
|
|
||||||
return el.InnerHTMLBySelectorAll(selector), nil
|
return el.InnerHTMLBySelectorAll(ctx, selector), nil
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
// @param doc (HTMLDocument|HTMLElement) - Parent document or element.
|
// @param doc (HTMLDocument|HTMLElement) - Parent document or element.
|
||||||
// @param selector (String, optional) - String of CSS selector.
|
// @param selector (String, optional) - String of CSS selector.
|
||||||
// @returns (String) - Inner text if an element found, otherwise empty string.
|
// @returns (String) - Inner text if an element found, otherwise empty string.
|
||||||
func InnerText(_ context.Context, args ...core.Value) (core.Value, error) {
|
func InnerText(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
err := core.ValidateArgs(args, 1, 2)
|
err := core.ValidateArgs(args, 1, 2)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -26,7 +26,7 @@ func InnerText(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
return el.InnerText(), nil
|
return el.InnerText(ctx), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err = core.ValidateType(args[1], types.String)
|
err = core.ValidateType(args[1], types.String)
|
||||||
@ -37,5 +37,5 @@ func InnerText(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
|
|
||||||
selector := args[1].(values.String)
|
selector := args[1].(values.String)
|
||||||
|
|
||||||
return el.InnerTextBySelector(selector), nil
|
return el.InnerTextBySelector(ctx, selector), nil
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
// @param doc (HTMLDocument|HTMLElement) - Parent document or element.
|
// @param doc (HTMLDocument|HTMLElement) - Parent document or element.
|
||||||
// @param selector (String) - String of CSS selector.
|
// @param selector (String) - String of CSS selector.
|
||||||
// @returns (String) - An array of inner text if any element found, otherwise empty array.
|
// @returns (String) - An array of inner text if any element found, otherwise empty array.
|
||||||
func InnerTextAll(_ context.Context, args ...core.Value) (core.Value, error) {
|
func InnerTextAll(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
err := core.ValidateArgs(args, 2, 2)
|
err := core.ValidateArgs(args, 2, 2)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -40,5 +40,5 @@ func InnerTextAll(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
|
|
||||||
selector := args[1].(values.String)
|
selector := args[1].(values.String)
|
||||||
|
|
||||||
return el.InnerTextBySelectorAll(selector), nil
|
return el.InnerTextBySelectorAll(ctx, selector), nil
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import (
|
|||||||
// @param value (String) - Target value.
|
// @param value (String) - Target value.
|
||||||
// @param delay (Int, optional) - Waits delay milliseconds between keystrokes
|
// @param delay (Int, optional) - Waits delay milliseconds between keystrokes
|
||||||
// @returns (Boolean) - Returns true if an element was found.
|
// @returns (Boolean) - Returns true if an element was found.
|
||||||
func Input(_ context.Context, args ...core.Value) (core.Value, error) {
|
func Input(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
err := core.ValidateArgs(args, 2, 4)
|
err := core.ValidateArgs(args, 2, 4)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -54,7 +54,7 @@ func Input(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
delay = arg4.(values.Int)
|
delay = arg4.(values.Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
return doc.InputBySelector(arg2.(values.String), args[2], delay)
|
return doc.InputBySelector(ctx, arg2.(values.String), args[2], delay)
|
||||||
}
|
}
|
||||||
|
|
||||||
el := arg1.(drivers.HTMLElement)
|
el := arg1.(drivers.HTMLElement)
|
||||||
@ -72,7 +72,7 @@ func Input(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
delay = arg3.(values.Int)
|
delay = arg3.(values.Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = el.Input(args[1], delay)
|
err = el.Input(ctx, args[1], delay)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return values.False, err
|
return values.False, err
|
||||||
|
@ -2,11 +2,11 @@ package html
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/MontFerret/ferret/pkg/drivers"
|
"github.com/MontFerret/ferret/pkg/drivers"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultTimeout = 5000
|
const defaultTimeout = 5000
|
||||||
@ -67,6 +67,13 @@ func ValidateDocument(ctx context.Context, value core.Value) (core.Value, error)
|
|||||||
return doc, nil
|
return doc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func waitTimeout(ctx context.Context, value values.Int) (context.Context, context.CancelFunc) {
|
||||||
|
return context.WithTimeout(
|
||||||
|
ctx,
|
||||||
|
time.Duration(value)*time.Millisecond,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func resolveElement(value core.Value) (drivers.HTMLElement, error) {
|
func resolveElement(value core.Value) (drivers.HTMLElement, error) {
|
||||||
vt := value.Type()
|
vt := value.Type()
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ package html
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
||||||
@ -14,7 +13,7 @@ import (
|
|||||||
// @param doc (Document) - Target document.
|
// @param doc (Document) - Target document.
|
||||||
// @param url (String) - Target url to navigate.
|
// @param url (String) - Target url to navigate.
|
||||||
// @param timeout (Int, optional) - Optional timeout. Default is 5000.
|
// @param timeout (Int, optional) - Optional timeout. Default is 5000.
|
||||||
func Navigate(_ context.Context, args ...core.Value) (core.Value, error) {
|
func Navigate(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
err := core.ValidateArgs(args, 2, 3)
|
err := core.ValidateArgs(args, 2, 3)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -39,5 +38,8 @@ func Navigate(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
timeout = args[2].(values.Int)
|
timeout = args[2].(values.Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
return values.None, doc.Navigate(args[1].(values.String), timeout)
|
ctx, fn := waitTimeout(ctx, timeout)
|
||||||
|
defer fn()
|
||||||
|
|
||||||
|
return values.None, doc.Navigate(ctx, args[1].(values.String))
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package html
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
||||||
@ -15,7 +14,7 @@ import (
|
|||||||
// @param entry (Int, optional) - Optional value indicating how many pages to skip. Default 1.
|
// @param entry (Int, optional) - Optional value indicating how many pages to skip. Default 1.
|
||||||
// @param timeout (Int, optional) - Optional timeout. Default is 5000.
|
// @param timeout (Int, optional) - Optional timeout. Default is 5000.
|
||||||
// @returns (Boolean) - Returns TRUE if history exists and the operation succeeded, otherwise FALSE.
|
// @returns (Boolean) - Returns TRUE if history exists and the operation succeeded, otherwise FALSE.
|
||||||
func NavigateBack(_ context.Context, args ...core.Value) (core.Value, error) {
|
func NavigateBack(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
err := core.ValidateArgs(args, 1, 3)
|
err := core.ValidateArgs(args, 1, 3)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -51,5 +50,8 @@ func NavigateBack(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
timeout = args[2].(values.Int)
|
timeout = args[2].(values.Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
return doc.NavigateBack(skip, timeout)
|
ctx, fn := waitTimeout(ctx, timeout)
|
||||||
|
defer fn()
|
||||||
|
|
||||||
|
return doc.NavigateBack(ctx, skip)
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package html
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
||||||
@ -15,7 +14,7 @@ import (
|
|||||||
// @param entry (Int, optional) - Optional value indicating how many pages to skip. Default 1.
|
// @param entry (Int, optional) - Optional value indicating how many pages to skip. Default 1.
|
||||||
// @param timeout (Int, optional) - Optional timeout. Default is 5000.
|
// @param timeout (Int, optional) - Optional timeout. Default is 5000.
|
||||||
// @returns (Boolean) - Returns TRUE if history exists and the operation succeeded, otherwise FALSE.
|
// @returns (Boolean) - Returns TRUE if history exists and the operation succeeded, otherwise FALSE.
|
||||||
func NavigateForward(_ context.Context, args ...core.Value) (core.Value, error) {
|
func NavigateForward(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
err := core.ValidateArgs(args, 1, 3)
|
err := core.ValidateArgs(args, 1, 3)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -51,5 +50,8 @@ func NavigateForward(_ context.Context, args ...core.Value) (core.Value, error)
|
|||||||
timeout = args[2].(values.Int)
|
timeout = args[2].(values.Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
return doc.NavigateForward(skip, timeout)
|
ctx, fn := waitTimeout(ctx, timeout)
|
||||||
|
defer fn()
|
||||||
|
|
||||||
|
return doc.NavigateForward(ctx, skip)
|
||||||
}
|
}
|
||||||
|
@ -85,14 +85,14 @@ func (p *Paging) Iterate(_ context.Context) (core.Iterator, error) {
|
|||||||
return &PagingIterator{p.document, p.selector, -1}, nil
|
return &PagingIterator{p.document, p.selector, -1}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *PagingIterator) Next(_ context.Context) (core.Value, core.Value, error) {
|
func (i *PagingIterator) Next(ctx context.Context) (core.Value, core.Value, error) {
|
||||||
i.pos++
|
i.pos++
|
||||||
|
|
||||||
if i.pos == 0 {
|
if i.pos == 0 {
|
||||||
return values.ZeroInt, values.ZeroInt, nil
|
return values.ZeroInt, values.ZeroInt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
clicked, err := i.document.ClickBySelector(i.selector)
|
clicked, err := i.document.ClickBySelector(ctx, i.selector)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return values.None, values.None, err
|
return values.None, values.None, err
|
||||||
|
@ -292,7 +292,7 @@ func PDF(ctx context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pdf, err := doc.PrintToPDF(pdfParams)
|
pdf, err := doc.PrintToPDF(ctx, pdfParams)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return values.None, err
|
return values.None, err
|
||||||
|
@ -155,7 +155,7 @@ func Screenshot(ctx context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scr, err := doc.CaptureScreenshot(screenshotParams)
|
scr, err := doc.CaptureScreenshot(ctx, screenshotParams)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return values.None, err
|
return values.None, err
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
// ScrollTop scrolls the document's window to its bottom.
|
// ScrollTop scrolls the document's window to its bottom.
|
||||||
// @param doc (HTMLDocument) - Target document.
|
// @param doc (HTMLDocument) - Target document.
|
||||||
func ScrollBottom(_ context.Context, args ...core.Value) (core.Value, error) {
|
func ScrollBottom(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
err := core.ValidateArgs(args, 1, 1)
|
err := core.ValidateArgs(args, 1, 1)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -29,5 +29,5 @@ func ScrollBottom(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
return values.None, err
|
return values.None, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return values.None, doc.ScrollBottom()
|
return values.None, doc.ScrollBottom(ctx)
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
// ScrollInto scrolls an element on.
|
// ScrollInto scrolls an element on.
|
||||||
// @param docOrEl (HTMLDocument|HTMLElement) - Target document or element.
|
// @param docOrEl (HTMLDocument|HTMLElement) - Target document or element.
|
||||||
// @param selector (String, options) - If document is passed, this param must represent an element selector.
|
// @param selector (String, options) - If document is passed, this param must represent an element selector.
|
||||||
func ScrollInto(_ context.Context, args ...core.Value) (core.Value, error) {
|
func ScrollInto(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
err := core.ValidateArgs(args, 1, 2)
|
err := core.ValidateArgs(args, 1, 2)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -36,7 +36,7 @@ func ScrollInto(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
doc := args[0].(drivers.HTMLDocument)
|
doc := args[0].(drivers.HTMLDocument)
|
||||||
selector := args[1].(values.String)
|
selector := args[1].(values.String)
|
||||||
|
|
||||||
return values.None, doc.ScrollBySelector(selector)
|
return values.None, doc.ScrollBySelector(ctx, selector)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = core.ValidateType(args[0], drivers.HTMLElementType)
|
err = core.ValidateType(args[0], drivers.HTMLElementType)
|
||||||
@ -48,5 +48,5 @@ func ScrollInto(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
// Element
|
// Element
|
||||||
el := args[0].(drivers.HTMLElement)
|
el := args[0].(drivers.HTMLElement)
|
||||||
|
|
||||||
return values.None, el.ScrollIntoView()
|
return values.None, el.ScrollIntoView(ctx)
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
// ScrollTop scrolls the document's window to its top.
|
// ScrollTop scrolls the document's window to its top.
|
||||||
// @param doc (HTMLDocument) - Target document.
|
// @param doc (HTMLDocument) - Target document.
|
||||||
func ScrollTop(_ context.Context, args ...core.Value) (core.Value, error) {
|
func ScrollTop(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
err := core.ValidateArgs(args, 1, 1)
|
err := core.ValidateArgs(args, 1, 1)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -29,5 +29,5 @@ func ScrollTop(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
return values.None, err
|
return values.None, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return values.None, doc.ScrollTop()
|
return values.None, doc.ScrollTop(ctx)
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
// @param valueOrSelector (String | Array<String>) - Selector or a an array of strings as a value.
|
// @param valueOrSelector (String | Array<String>) - Selector or a an array of strings as a value.
|
||||||
// @param value (Array<String) - Target value. Optional.
|
// @param value (Array<String) - Target value. Optional.
|
||||||
// @returns (Array<String>) - Returns an array of selected values.
|
// @returns (Array<String>) - Returns an array of selected values.
|
||||||
func Select(_ context.Context, args ...core.Value) (core.Value, error) {
|
func Select(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
err := core.ValidateArgs(args, 2, 4)
|
err := core.ValidateArgs(args, 2, 4)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -46,7 +46,7 @@ func Select(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
return values.False, err
|
return values.False, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return doc.SelectBySelector(arg2.(values.String), arg3.(*values.Array))
|
return doc.SelectBySelector(ctx, arg2.(values.String), arg3.(*values.Array))
|
||||||
}
|
}
|
||||||
|
|
||||||
el := arg1.(drivers.HTMLElement)
|
el := arg1.(drivers.HTMLElement)
|
||||||
@ -58,5 +58,5 @@ func Select(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
return values.False, err
|
return values.False, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return el.Select(arg2.(*values.Array))
|
return el.Select(ctx, arg2.(*values.Array))
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package html
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/MontFerret/ferret/pkg/drivers"
|
"github.com/MontFerret/ferret/pkg/drivers"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||||
@ -18,7 +17,7 @@ import (
|
|||||||
// Otherwise timeout.
|
// Otherwise timeout.
|
||||||
// @param timeout (Int, optional) - If document is passed, this param must represent timeout.
|
// @param timeout (Int, optional) - If document is passed, this param must represent timeout.
|
||||||
// Otherwise not passed.
|
// Otherwise not passed.
|
||||||
func WaitClass(_ context.Context, args ...core.Value) (core.Value, error) {
|
func WaitClass(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
err := core.ValidateArgs(args, 2, 4)
|
err := core.ValidateArgs(args, 2, 4)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -72,7 +71,10 @@ func WaitClass(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
timeout = args[3].(values.Int)
|
timeout = args[3].(values.Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
return values.None, doc.WaitForClassBySelector(selector, class, timeout)
|
ctx, fn := waitTimeout(ctx, timeout)
|
||||||
|
defer fn()
|
||||||
|
|
||||||
|
return values.None, doc.WaitForClassBySelector(ctx, selector, class)
|
||||||
}
|
}
|
||||||
|
|
||||||
el := arg1.(drivers.HTMLElement)
|
el := arg1.(drivers.HTMLElement)
|
||||||
@ -88,5 +90,8 @@ func WaitClass(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
timeout = args[2].(values.Int)
|
timeout = args[2].(values.Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
return values.None, el.WaitForClass(class, timeout)
|
ctx, fn := waitTimeout(ctx, timeout)
|
||||||
|
defer fn()
|
||||||
|
|
||||||
|
return values.None, el.WaitForClass(ctx, class)
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package html
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
||||||
@ -14,7 +13,7 @@ import (
|
|||||||
// @param selector (String) - String of CSS selector.
|
// @param selector (String) - String of CSS selector.
|
||||||
// @param class (String) - String of target CSS class.
|
// @param class (String) - String of target CSS class.
|
||||||
// @param timeout (Int, optional) - Optional timeout.
|
// @param timeout (Int, optional) - Optional timeout.
|
||||||
func WaitClassAll(_ context.Context, args ...core.Value) (core.Value, error) {
|
func WaitClassAll(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
err := core.ValidateArgs(args, 3, 4)
|
err := core.ValidateArgs(args, 3, 4)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -55,5 +54,8 @@ func WaitClassAll(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
timeout = args[3].(values.Int)
|
timeout = args[3].(values.Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
return values.None, doc.WaitForClassBySelectorAll(selector, class, timeout)
|
ctx, fn := waitTimeout(ctx, timeout)
|
||||||
|
defer fn()
|
||||||
|
|
||||||
|
return values.None, doc.WaitForClassBySelectorAll(ctx, selector, class)
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package html
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
||||||
@ -13,7 +12,7 @@ import (
|
|||||||
// @param doc (HTMLDocument) - Driver HTMLDocument.
|
// @param doc (HTMLDocument) - Driver HTMLDocument.
|
||||||
// @param selector (String) - Target element's selector.
|
// @param selector (String) - Target element's selector.
|
||||||
// @param timeout (Int, optional) - Optional timeout. Default 5000 ms.
|
// @param timeout (Int, optional) - Optional timeout. Default 5000 ms.
|
||||||
func WaitElement(_ context.Context, args ...core.Value) (core.Value, error) {
|
func WaitElement(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
err := core.ValidateArgs(args, 2, 3)
|
err := core.ValidateArgs(args, 2, 3)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -39,5 +38,8 @@ func WaitElement(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
timeout = args[2].(values.Int)
|
timeout = args[2].(values.Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
return values.None, doc.WaitForSelector(values.NewString(selector), timeout)
|
ctx, fn := waitTimeout(ctx, timeout)
|
||||||
|
defer fn()
|
||||||
|
|
||||||
|
return values.None, doc.WaitForSelector(ctx, values.NewString(selector))
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package html
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
||||||
@ -12,7 +11,7 @@ import (
|
|||||||
// Stops the execution until the navigation ends or operation times out.
|
// Stops the execution until the navigation ends or operation times out.
|
||||||
// @param doc (HTMLDocument) - Driver HTMLDocument.
|
// @param doc (HTMLDocument) - Driver HTMLDocument.
|
||||||
// @param timeout (Int, optional) - Optional timeout. Default 5000 ms.
|
// @param timeout (Int, optional) - Optional timeout. Default 5000 ms.
|
||||||
func WaitNavigation(_ context.Context, args ...core.Value) (core.Value, error) {
|
func WaitNavigation(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
err := core.ValidateArgs(args, 1, 2)
|
err := core.ValidateArgs(args, 1, 2)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -37,5 +36,8 @@ func WaitNavigation(_ context.Context, args ...core.Value) (core.Value, error) {
|
|||||||
timeout = args[1].(values.Int)
|
timeout = args[1].(values.Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
return values.None, doc.WaitForNavigation(timeout)
|
ctx, fn := waitTimeout(ctx, timeout)
|
||||||
|
defer fn()
|
||||||
|
|
||||||
|
return values.None, doc.WaitForNavigation(ctx)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user