(code: str)
| 1387 | |
| 1388 | @beartype |
| 1389 | def parse_playwright_code(code: str) -> list[ParsedPlaywrightCode]: |
| 1390 | # extract function calls |
| 1391 | if not code.startswith("page."): |
| 1392 | raise ValueError( |
| 1393 | f'Playwright action must start with "page.", but got {code}' |
| 1394 | ) |
| 1395 | |
| 1396 | regex = r"\.(?![^\(\)]*\))" |
| 1397 | chain = re.split(regex, code)[1:] |
| 1398 | |
| 1399 | parsed_chain = [] |
| 1400 | |
| 1401 | for item in chain: |
| 1402 | tree = ast.parse(item) |
| 1403 | funcs = [] |
| 1404 | for node in ast.walk(tree): |
| 1405 | if isinstance(node, ast.Call): |
| 1406 | function_name = node.func.id # type: ignore[attr-defined] |
| 1407 | arguments = [ |
| 1408 | ast.literal_eval(arg) if isinstance(arg, ast.Str) else arg |
| 1409 | for arg in node.args |
| 1410 | ] |
| 1411 | keywords = { |
| 1412 | str(kw.arg): ast.literal_eval(kw.value) |
| 1413 | for kw in node.keywords |
| 1414 | } |
| 1415 | funcs.append( |
| 1416 | ParsedPlaywrightCode( |
| 1417 | { |
| 1418 | "function_name": function_name, |
| 1419 | "arguments": arguments, |
| 1420 | "keywords": keywords, |
| 1421 | } |
| 1422 | ) |
| 1423 | ) |
| 1424 | |
| 1425 | if len(funcs) != 1: |
| 1426 | raise ValueError(f"Fail to parse {item} in {code}") |
| 1427 | |
| 1428 | if ( |
| 1429 | funcs[0]["function_name"] |
| 1430 | not in PLAYWRIGHT_LOCATORS + PLAYWRIGHT_ACTIONS |
| 1431 | ): |
| 1432 | raise ValueError( |
| 1433 | f"Invalid playwright code {item}, ", |
| 1434 | f"the function needs to be one of {PLAYWRIGHT_LOCATORS + PLAYWRIGHT_ACTIONS}", |
| 1435 | ) |
| 1436 | |
| 1437 | parsed_chain.append(funcs[0]) |
| 1438 | |
| 1439 | last_action = parsed_chain[-1] |
| 1440 | if last_action["function_name"] not in PLAYWRIGHT_ACTIONS: |
| 1441 | raise ValueError( |
| 1442 | f"Invalid playwright action {last_action},", |
| 1443 | f"the action needs to be one of {PLAYWRIGHT_ACTIONS}", |
| 1444 | ) |
| 1445 | |
| 1446 | return parsed_chain |
no test coverage detected