diff --git a/help_docs/method_summary.md b/help_docs/method_summary.md index 8d1a7fc5e90..a9267810148 100644 --- a/help_docs/method_summary.md +++ b/help_docs/method_summary.md @@ -250,6 +250,7 @@ self.save_screenshot_to_logs(name=None, selector=None, by="css selector") self.save_data_to_logs(data, file_name=None) self.append_data_to_logs(data, file_name=None) self.save_page_source(name, folder=None) +self.save_page_source_to_logs(name=None) self.save_cookies(name="cookies.txt") self.load_cookies(name="cookies.txt", expiry=False) self.delete_all_cookies() diff --git a/requirements.txt b/requirements.txt index 518dd017140..3806ba3b716 100755 --- a/requirements.txt +++ b/requirements.txt @@ -46,7 +46,7 @@ wsproto==1.2.0 websocket-client==1.8.0 selenium==4.27.1;python_version<"3.9" selenium==4.32.0;python_version>="3.9" and python_version<"3.10" -selenium==4.34.1;python_version>="3.10" +selenium==4.34.2;python_version>="3.10" cssselect==1.2.0;python_version<"3.9" cssselect==1.3.0;python_version>="3.9" sortedcontainers==2.4.0 diff --git a/sbase/steps.py b/sbase/steps.py index 871ce6aaca0..f2078f94882 100644 --- a/sbase/steps.py +++ b/sbase/steps.py @@ -1191,6 +1191,15 @@ def set_attributes(context, selector, attribute, value): sb.set_attributes(selector, attribute, value) +@step("Save page source to logs") +@step("Save the page source to the logs") +@step("User saves page source to logs") +@step("User saves the page source to the logs") +def save_page_source_to_logs(context): + sb = context.sb + sb.save_page_source_to_logs() + + @step("Activate CDP Mode") @step("User activates CDP Mode") def activate_cdp_mode(context): diff --git a/seleniumbase/__version__.py b/seleniumbase/__version__.py index 4518f790cd0..60a75a7ccaf 100755 --- a/seleniumbase/__version__.py +++ b/seleniumbase/__version__.py @@ -1,2 +1,2 @@ # seleniumbase package -__version__ = "4.40.1" +__version__ = "4.40.2" diff --git a/seleniumbase/behave/behave_helper.py b/seleniumbase/behave/behave_helper.py index 8e45cae2514..fbd9548df19 100644 --- a/seleniumbase/behave/behave_helper.py +++ b/seleniumbase/behave/behave_helper.py @@ -522,6 +522,8 @@ def generate_gherkin(srt_actions): ) elif action[0] == "ss_tl": sb_actions.append("Save screenshot to logs") + elif action[0] == "spstl": + sb_actions.append("Save page source to logs") elif action[0] == "sh_fc": sb_actions.append("Show file choosers") elif action[0] == "pr_da": diff --git a/seleniumbase/core/recorder_helper.py b/seleniumbase/core/recorder_helper.py index 40f9cef4a6f..6f3802d86b9 100644 --- a/seleniumbase/core/recorder_helper.py +++ b/seleniumbase/core/recorder_helper.py @@ -556,6 +556,9 @@ def generate_sbase_code(srt_actions): elif action[0] == "ss_tl": method = "save_screenshot_to_logs" sb_actions.append("self.%s()" % method) + elif action[0] == "spstl": + method = "save_page_source_to_logs" + sb_actions.append("self.%s()" % method) elif action[0] == "sh_fc": method = "show_file_choosers" sb_actions.append("self.%s()" % method) diff --git a/seleniumbase/fixtures/base_case.py b/seleniumbase/fixtures/base_case.py index d5da1cf966e..8c8018e4031 100644 --- a/seleniumbase/fixtures/base_case.py +++ b/seleniumbase/fixtures/base_case.py @@ -132,6 +132,7 @@ def __initialize_variables(self): self.__called_teardown = False self.__start_time_ms = int(time.time() * 1000.0) self.__requests_timeout = None + self.__page_source_count = 0 self.__screenshot_count = 0 self.__logs_data_count = 0 self.__last_data_file = None @@ -4512,6 +4513,40 @@ def save_screenshot_to_logs( sb_config._has_logs = True return page_actions.save_screenshot(self.driver, name, test_logpath) + def save_page_source_to_logs(self, name=None): + """Saves the page HTML to the "latest_logs/" folder. + Naming is automatic: + If NO NAME provided: "_1_source.html", "_2_source.html", etc. + If NAME IS provided, then: "_1_name.html", "_2_name.html", etc. + (The last_page / failure page_source is always "page_source.html")""" + if not self.__is_cdp_swap_needed(): + self.wait_for_ready_state_complete() + test_logpath = os.path.join(self.log_path, self.__get_test_id()) + self.__create_log_path_as_needed(test_logpath) + if name: + name = str(name) + self.__page_source_count += 1 + if not name or len(name) == 0: + name = "_%s_source.html" % self.__page_source_count + else: + pre_name = "_%s_" % self.__page_source_count + if len(name) >= 4 and name[-4:].lower() == ".html": + name = name[:-4] + if len(name) == 0: + name = "source" + name = "%s%s.html" % (pre_name, name) + if self.recorder_mode: + url = self.get_current_url() + if url and len(url) > 0: + if ("http:") in url or ("https:") in url or ("file:") in url: + if self.get_session_storage_item("pause_recorder") == "no": + time_stamp = self.execute_script("return Date.now();") + origin = self.get_origin() + action = ["spstl", "", origin, time_stamp] + self.__extra_actions.append(action) + sb_config._has_logs = True + return page_actions.save_page_source(self.driver, name, test_logpath) + def save_data_to_logs(self, data, file_name=None): """Saves data to the "latest_logs/" data folder of the current test. If no file_name, file_name becomes: "data_1.txt", "data_2.txt", etc. @@ -5470,6 +5505,7 @@ def __process_recorded_actions(self): ext_actions.append("s_scr") ext_actions.append("ss_tf") ext_actions.append("ss_tl") + ext_actions.append("spstl") ext_actions.append("da_el") ext_actions.append("da_ep") ext_actions.append("da_te") diff --git a/setup.py b/setup.py index 69de9f53165..a7279207bf0 100755 --- a/setup.py +++ b/setup.py @@ -194,7 +194,7 @@ 'websocket-client==1.8.0', 'selenium==4.27.1;python_version<"3.9"', 'selenium==4.32.0;python_version>="3.9" and python_version<"3.10"', - 'selenium==4.34.1;python_version>="3.10"', + 'selenium==4.34.2;python_version>="3.10"', 'cssselect==1.2.0;python_version<"3.9"', 'cssselect==1.3.0;python_version>="3.9"', "sortedcontainers==2.4.0",