1
+ import os
2
+ import ast
3
+ import itertools
4
+
5
+ files_to_skip = [
6
+ # Console Domain Disabled
7
+ 'test_console.py' ,
8
+
9
+ # query_selector is deprecated
10
+ 'test_element_handle.py' ,
11
+ 'test_element_handle_wait_for_element_state.py' ,
12
+
13
+ # https://github.com/Kaliiiiiiiiii-Vinyzu/patchright/issues/31
14
+ 'test_route_web_socket.py'
15
+ ]
16
+
17
+ tests_to_skip = [
18
+ # Disabled Console Domain
19
+ "test_block_blocks_service_worker_registration" ,
20
+ "test_console_event_should_work" ,
21
+ "test_console_event_should_work_in_popup" ,
22
+ "test_console_event_should_work_in_popup_2" ,
23
+ "test_console_event_should_work_in_immediately_closed_popup" ,
24
+ "test_dialog_event_should_work_in_immdiately_closed_popup" ,
25
+ "test_console_event_should_work_with_context_manager" ,
26
+ "test_weberror_event_should_work" ,
27
+ "test_console_repr" ,
28
+ "test_console_should_work" ,
29
+ "test_should_collect_trace_with_resources_but_no_js" ,
30
+ "test_should_work_with_playwright_context_managers" ,
31
+ "test_should_respect_traces_dir_and_name" ,
32
+ "test_should_show_tracing_group_in_action_list" ,
33
+ "test_page_error_event_should_work" ,
34
+ "test_click_offscreen_buttons" ,
35
+ "test_watch_position_should_be_notified" ,
36
+ "test_page_error_should_fire" ,
37
+ "test_page_error_should_handle_odd_values" ,
38
+ "test_page_error_should_handle_object" ,
39
+ "test_page_error_should_handle_window" ,
40
+ "test_page_error_should_pass_error_name_property" ,
41
+ "test_workers_should_report_console_logs" ,
42
+ "test_workers_should_have_JSHandles_for_console_logs" ,
43
+ "test_workers_should_report_errors" ,
44
+
45
+ # InitScript Timing
46
+ "test_expose_function_should_be_callable_from_inside_add_init_script" ,
47
+ "test_expose_bindinghandle_should_work" ,
48
+ "test_browser_context_add_init_script_should_apply_to_an_in_process_popup" ,
49
+ "test_should_expose_function_from_browser_context" ,
50
+
51
+ # Disable Popup Blocking
52
+ "test_page_event_should_have_an_opener" ,
53
+
54
+ # query_selector is deprecated
55
+ "test_should_work_with_layout_selectors" ,
56
+ "test_should_dispatch_click_event_element_handle" ,
57
+ "test_should_dispatch_drag_and_drop_events_element_handle" ,
58
+
59
+ # Minor Differences in Call Log. Deemed Unimportant
60
+ "test_should_be_attached_fail_with_not" ,
61
+ "test_add_script_tag_should_include_source_url_when_path_is_provided" ,
62
+
63
+ # Server/Client Header Mismatch
64
+ "test_should_report_request_headers_array" ,
65
+ "test_request_headers_should_get_the_same_headers_as_the_server_cors" ,
66
+ "test_request_headers_should_get_the_same_headers_as_the_server" ,
67
+ ]
68
+
69
+ dont_isolate_evaluation_tests = [
70
+ "test_timeout_waiting_for_stable_position" ,
71
+ "test_jshandle_evaluate_accept_object_handle_as_argument" ,
72
+ "test_jshandle_evaluate_accept_nested_handle" ,
73
+ "test_jshandle_evaluate_accept_nested_window_handle" ,
74
+ "test_jshandle_evaluate_accept_multiple_nested_handles" ,
75
+ "test_should_dispatch_drag_drop_events" ,
76
+ "test_should_dispatch_drag_and_drop_events_element_handle" ,
77
+ "track_events" ,
78
+ "captureLastKeydown" ,
79
+ "test_expose_function_should_work_on_frames_before_navigation" ,
80
+ ]
81
+
82
+ # Directory containing the test files
83
+ async_test_dir = 'tests/async'
84
+ sync_test_dir = 'tests/sync'
85
+
86
+ # Reason for skipping tests_backup
87
+ skip_reason = "Skipped as per documentation (https://github.com/Kaliiiiiiiiii-Vinyzu/patchright/issues/31)"
88
+
89
+
90
+ class ParentAnnotator (ast .NodeVisitor ):
91
+ def __init__ (self ):
92
+ self .parents = {}
93
+
94
+ def visit (self , node ):
95
+ for child in ast .iter_child_nodes (node ):
96
+ self .parents [child ] = node
97
+ self .visit (child )
98
+
99
+ def process_file (file_path ):
100
+ with open (file_path , 'r' , encoding = 'utf-8' ) as f :
101
+ source = f .read ()
102
+
103
+ file_tree = ast .parse (source )
104
+ annotator = ParentAnnotator ()
105
+ annotator .visit (file_tree )
106
+
107
+ for node in ast .walk (file_tree ):
108
+ # Rename Playwright Imports to Patchright
109
+ if isinstance (node , ast .Import ):
110
+ for alias in node .names :
111
+ if alias .name .startswith ("playwright" ):
112
+ alias .name = alias .name .replace ("playwright" , "patchright" , 1 )
113
+ if isinstance (node , ast .ImportFrom ) and node .module .startswith ("playwright" ):
114
+ node .module = node .module .replace ("playwright" , "patchright" , 1 )
115
+
116
+ # Skip Tests Documented: https://github.com/Kaliiiiiiiiii-Vinyzu/patchright/issues/31
117
+ if isinstance (node , ast .FunctionDef ) or isinstance (node , ast .AsyncFunctionDef ):
118
+ # Add Server Arg to test_add_init_script Tests
119
+ if "test_add_init_script" in file_path :
120
+ node .args .args .append (ast .arg (arg = 'server' , annotation = None ))
121
+ # Skip Tests to skip
122
+ if node .name in tests_to_skip :
123
+ skip_decorator = ast .parse (f"@pytest.mark.skip(reason='{ skip_reason } ')\n def placeholder(): return" ).body [0 ].decorator_list [0 ]
124
+ node .decorator_list .insert (0 , skip_decorator )
125
+
126
+ # Add isolated_context=False to every necessary evaluate/evaluate_handle Call
127
+ if isinstance (node , ast .Call ) and isinstance (node .func , ast .Attribute ):
128
+ # Very Bad Hack to get the parent node
129
+ test_name = ""
130
+ current_node = node
131
+ while annotator .parents .get (current_node ):
132
+ current_node = annotator .parents [current_node ]
133
+ if isinstance (current_node , ast .FunctionDef ) or isinstance (current_node , ast .AsyncFunctionDef ):
134
+ test_name = current_node .name
135
+
136
+ if test_name in dont_isolate_evaluation_tests :
137
+ # Don't add isolated_context=False to these tests
138
+ continue
139
+
140
+ if node .func .attr in ("evaluate" , "evaluate_handle" , "evaluate_all" ) and isinstance (node .func .value , ast .Name ) and node .func .value .id in ("page" , "popup" , "button" , "new_page" , "page1" , "page2" , "target" , "page_1" , "page_2" , "frame" ):
141
+ node .keywords .append (ast .keyword (arg = 'isolated_context' , value = ast .Constant (value = False )))
142
+
143
+ modified_source = ast .unparse (ast .fix_missing_locations (file_tree ))
144
+
145
+ with open (file_path , 'w' , encoding = 'utf-8' ) as f :
146
+ f .write (modified_source )
147
+
148
+ def main ():
149
+ with open ("./tests/assets/inject.html" , "w" ) as f :
150
+ f .write ("<script>window.result = window.injected;</script>" )
151
+
152
+ for root , _ , files in itertools .chain (os .walk (sync_test_dir ), os .walk (async_test_dir )):
153
+ for file in files :
154
+ file_path = os .path .join (root , file )
155
+
156
+ # Init Script Behaviour https://github.com/Kaliiiiiiiiii-Vinyzu/patchright/issues/30
157
+ if file == "test_add_init_script.py" :
158
+ with open (file_path , 'r' , encoding = 'utf-8' ) as f :
159
+ content = f .read ()
160
+
161
+ # Replace the full quoted strings with valid Python expressions (not strings)
162
+ content = content .replace (
163
+ '"data:text/html,<script>window.result = window.injected</script>"' ,
164
+ 'server.PREFIX + "/inject.html"'
165
+ ).replace (
166
+ '"data:text/html,<html></html>"' ,
167
+ 'server.PREFIX + "/empty.html"'
168
+ )
169
+
170
+ with open (file_path , 'w' , encoding = 'utf-8' ) as f :
171
+ f .write (content )
172
+
173
+ # Init Script Behaviour https://github.com/Kaliiiiiiiiii-Vinyzu/patchright/issues/30
174
+ if file == "test_page_clock.py" :
175
+ with open (file_path , 'r' , encoding = 'utf-8' ) as f :
176
+ content = f .read ()
177
+
178
+ # Replace the full quoted strings with valid Python expressions (not strings)
179
+ content = content .replace (
180
+ "about:blank" ,
181
+ "https://www.google.com/blank.html"
182
+ ).replace (
183
+ "data:text/html," ,
184
+ "https://www.google.com/blank.html"
185
+ )
186
+
187
+ with open (file_path , 'w' , encoding = 'utf-8' ) as f :
188
+ f .write (content )
189
+
190
+ # Import Pytest
191
+ if file in ("test_browsercontext_service_worker_policy.py" , "test_tracing.py" , "test_popup.py" , "test_dispatch_event.py" ):
192
+ # Append "import pytest" to the top of the file
193
+ with open (file_path , 'r+' , encoding = 'utf-8' ) as f :
194
+ content = f .read ()
195
+ if "import pytest" not in content :
196
+ f .seek (0 , 0 )
197
+ f .write ("import pytest\n " + content )
198
+
199
+ # Skipping Files
200
+ if file in files_to_skip :
201
+ # Delete File
202
+ os .remove (file_path )
203
+ continue
204
+
205
+ if file .endswith ('.py' ):
206
+ process_file (file_path )
207
+
208
+ if __name__ == '__main__' :
209
+ main ()
0 commit comments