1# Copyright 2024 The Chromium Authors 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5from __future__ import annotations 6 7import datetime as dt 8from typing import TYPE_CHECKING, Type 9 10from crossbench.action_runner.action.action import ACTION_TIMEOUT, ActionT 11from crossbench.action_runner.action.action_type import ActionType 12from crossbench.action_runner.action.base_duration import BaseDurationAction 13from crossbench.action_runner.action.enums import ReadyState, WindowTarget 14from crossbench.parse import DurationParser, ObjectParser 15 16if TYPE_CHECKING: 17 from crossbench.action_runner.base import ActionRunner 18 from crossbench.config import ConfigParser 19 from crossbench.runner.run import Run 20 from crossbench.types import JsonDict 21 22 23class GetAction(BaseDurationAction): 24 TYPE: ActionType = ActionType.GET 25 26 @classmethod 27 def parse_str(cls, value: str) -> GetAction: 28 return cls(url=ObjectParser.parse_fuzzy_url_str(value)) 29 30 @classmethod 31 def config_parser(cls: Type[ActionT]) -> ConfigParser[ActionT]: 32 parser = super().config_parser() 33 parser.add_argument( 34 "url", type=ObjectParser.parse_fuzzy_url_str, required=True) 35 parser.add_argument( 36 "duration", 37 type=DurationParser.positive_or_zero_duration, 38 default=dt.timedelta()) 39 parser.add_argument( 40 "ready_state", type=ReadyState.parse, default=ReadyState.ANY) 41 parser.add_argument( 42 "target", type=WindowTarget.parse, default=WindowTarget.SELF) 43 return parser 44 45 def __init__(self, 46 url: str, 47 duration: dt.timedelta = dt.timedelta(), 48 timeout: dt.timedelta = ACTION_TIMEOUT, 49 ready_state: ReadyState = ReadyState.ANY, 50 target: WindowTarget = WindowTarget.SELF, 51 index: int = 0): 52 if not url: 53 raise ValueError(f"{self}.url is missing") 54 self._url: str = url 55 self._ready_state = ready_state 56 self._target = target 57 super().__init__(duration, timeout, index) 58 59 def validate_duration(self) -> None: 60 if self.ready_state != ReadyState.ANY: 61 if self.duration != dt.timedelta(): 62 raise ValueError( 63 f"Expected empty duration with ReadyState {self.ready_state} " 64 f"but got: {self.duration}") 65 self._duration = dt.timedelta() 66 67 @property 68 def url(self) -> str: 69 return self._url 70 71 @property 72 def ready_state(self) -> ReadyState: 73 return self._ready_state 74 75 @property 76 def duration(self) -> dt.timedelta: 77 return self._duration 78 79 @property 80 def target(self) -> WindowTarget: 81 return self._target 82 83 def run_with(self, run: Run, action_runner: ActionRunner) -> None: 84 action_runner.get(run, self) 85 86 def to_json(self) -> JsonDict: 87 details = super().to_json() 88 details["url"] = self.url 89 details["ready_state"] = str(self.ready_state) 90 details["target"] = str(self.target) 91 return details 92