mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-04 20:17:09 +00:00
refactor(runner): collapse WebDriver forks behind ActionSource/ExtractorSource
This commit is contained in:
1 parent
0436c6094e
commit
1a17734ce0
2 files changed
+91
-30
No files matched your search
@@ -0,0 +1,72 @@
|
||||
package runner
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/priyanshujain/sanderling/internal/driver"
|
||||
"github.com/priyanshujain/sanderling/internal/verifier"
|
||||
)
|
||||
|
||||
// ActionSource resolves the next action for a step. Both runtimes (the goja
|
||||
// picker and the web/V8 picker) implement it so the runner loop has one path
|
||||
// and no per-step driver type assertion. NextAction returns verifier.ErrNoAction
|
||||
// when the picker declined to act this tick.
|
||||
type ActionSource interface {
|
||||
NextAction(ctx context.Context) (verifier.Action, error)
|
||||
}
|
||||
|
||||
// ExtractorSource yields per-step extractor overrides the runner applies after
|
||||
// PushSnapshot. The mobile path has none (returns nil); the web path returns the
|
||||
// values its extractors computed in V8 against the real DOM.
|
||||
type ExtractorSource interface {
|
||||
ExtractorOverrides(ctx context.Context) (map[int]json.RawMessage, error)
|
||||
}
|
||||
|
||||
// gojaSource drives both action selection and (trivially) extractor overrides
|
||||
// for the mobile path, where the goja-bundled picker runs in-process and no V8
|
||||
// extractor values exist.
|
||||
type gojaSource struct {
|
||||
verifier *verifier.Verifier
|
||||
}
|
||||
|
||||
func (s gojaSource) NextAction(context.Context) (verifier.Action, error) {
|
||||
return s.verifier.NextAction()
|
||||
}
|
||||
|
||||
func (gojaSource) ExtractorOverrides(context.Context) (map[int]json.RawMessage, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// webSource adapts the chrome driver's V8 picker: it evaluates the bundled
|
||||
// __sanderlingNextAction__ / __sanderlingExtractors__ globals and decodes their
|
||||
// JSON into the unified action and override shapes.
|
||||
type webSource struct {
|
||||
web driver.WebDriver
|
||||
}
|
||||
|
||||
func (s webSource) NextAction(ctx context.Context) (verifier.Action, error) {
|
||||
raw, err := s.web.NextActionFromV8(ctx)
|
||||
if err != nil {
|
||||
return verifier.Action{}, fmt.Errorf("v8 next action: %w", err)
|
||||
}
|
||||
// Both engines emit the unified flat camelCase wire contract; one decoder
|
||||
// reads it. A null payload means the generator declined to act this tick.
|
||||
return verifier.DecodeAction(raw)
|
||||
}
|
||||
|
||||
func (s webSource) ExtractorOverrides(ctx context.Context) (map[int]json.RawMessage, error) {
|
||||
return s.web.EvaluateExtractors(ctx)
|
||||
}
|
||||
|
||||
// pickSources selects the runtime's action and extractor sources ONCE at setup
|
||||
// from the driver's capabilities, so the step loop never type-asserts.
|
||||
func pickSources(options Options) (ActionSource, ExtractorSource) {
|
||||
if web, ok := options.Driver.(driver.WebDriver); ok {
|
||||
source := webSource{web: web}
|
||||
return source, source
|
||||
}
|
||||
source := gojaSource{verifier: options.Verifier}
|
||||
return source, source
|
||||
}
|
||||
Reference in new issue
Block a user