From 111a8419f93cb9afec22c0a759ec2dd10327280b Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Thu, 13 Mar 2025 18:49:42 -0700 Subject: [PATCH 1/3] Simplify bootstrap form tests --- tests/test_app/forms/components.py | 4 +- tests/test_app/forms/forms.py | 7 +++ tests/test_app/tests/test_components.py | 73 +++---------------------- 3 files changed, 17 insertions(+), 67 deletions(-) diff --git a/tests/test_app/forms/components.py b/tests/test_app/forms/components.py index 26ab8704..112b7811 100644 --- a/tests/test_app/forms/components.py +++ b/tests/test_app/forms/components.py @@ -2,7 +2,7 @@ from reactpy_django.components import django_form -from .forms import BasicForm, DatabaseBackedForm, EventForm +from .forms import BasicForm, BootstrapForm, DatabaseBackedForm, EventForm @component @@ -13,7 +13,7 @@ def basic_form(): @component def bootstrap_form(): return django_form( - BasicForm, + BootstrapForm, extra_props={"style": {"maxWidth": "600px", "margin": "auto"}}, form_template="bootstrap_form_template.html", ) diff --git a/tests/test_app/forms/forms.py b/tests/test_app/forms/forms.py index 6b8dedd6..6fe79dc2 100644 --- a/tests/test_app/forms/forms.py +++ b/tests/test_app/forms/forms.py @@ -48,3 +48,10 @@ class Meta: class EventForm(forms.Form): char_field = forms.CharField(label="chars") + + +class BootstrapForm(forms.Form): + # Render a handful of Django field types + boolean_field = forms.BooleanField(label="boolean") + char_field = forms.CharField(label="chars") + choice_field = forms.ChoiceField(label="choice", choices=[("1", "One"), ("2", "Two")]) diff --git a/tests/test_app/tests/test_components.py b/tests/test_app/tests/test_components.py index e04a66f6..4978c236 100644 --- a/tests/test_app/tests/test_components.py +++ b/tests/test_app/tests/test_components.py @@ -776,10 +776,10 @@ def test_form_basic(self): model_choice_field_values[2], ]) + # Submit and wait for one of the error messages to disappear (indicating that the form has been re-rendered) + invalid_feedback = self.page.locator(".errorlist").all()[0] self.page.wait_for_selector("input[type=submit]").click(delay=CLICK_DELAY) - - # Wait for one of the error messages to disappear (indicating that the form has been re-rendered) - expect(self.page.locator(".errorlist").all()[0]).not_to_be_attached() + expect(invalid_feedback).not_to_be_attached() # Make sure no errors remain assert len(self.page.query_selector_all(".errorlist")) == 0 @@ -801,82 +801,25 @@ def test_form_bootstrap(self): self.page.wait_for_selector("#id_boolean_field") self.page.wait_for_selector("#id_char_field") self.page.wait_for_selector("#id_choice_field") - self.page.wait_for_selector("#id_date_field") - self.page.wait_for_selector("#id_date_time_field") - self.page.wait_for_selector("#id_decimal_field") - self.page.wait_for_selector("#id_duration_field") - self.page.wait_for_selector("#id_email_field") - self.page.wait_for_selector("#id_file_path_field") - self.page.wait_for_selector("#id_float_field") - self.page.wait_for_selector("#id_generic_ip_address_field") - self.page.wait_for_selector("#id_integer_field") - self.page.wait_for_selector("#id_float_field") - self.page.wait_for_selector("#id_json_field") - self.page.wait_for_selector("#id_multiple_choice_field") - self.page.wait_for_selector("#id_null_boolean_field") - self.page.wait_for_selector("#id_regex_field") - self.page.wait_for_selector("#id_slug_field") - self.page.wait_for_selector("#id_time_field") - self.page.wait_for_selector("#id_typed_choice_field") - self.page.wait_for_selector("#id_typed_multiple_choice_field") - self.page.wait_for_selector("#id_url_field") - self.page.wait_for_selector("#id_uuid_field") - self.page.wait_for_selector("#id_combo_field") - self.page.wait_for_selector("#id_password_field") - self.page.wait_for_selector("#id_model_choice_field") - self.page.wait_for_selector("#id_model_multiple_choice_field") sleep(1) self.page.wait_for_selector("button[type=submit]").click(delay=CLICK_DELAY) self.page.wait_for_selector(".invalid-feedback") - # Submitting an empty form should result in 22 error elements. + # Submitting an empty form should result in 2 error elements. # The number of errors may change if/when new test form elements are created. - assert len(self.page.query_selector_all(".invalid-feedback")) == 22 + assert len(self.page.query_selector_all(".invalid-feedback")) == 2 # Fill out the form self.page.wait_for_selector("#id_boolean_field").click(delay=CLICK_DELAY) expect(self.page.locator("#id_boolean_field")).to_be_checked() - self.page.locator("#id_char_field").type("test", delay=CLICK_DELAY) self.page.locator("#id_choice_field").select_option("2") - self.page.locator("#id_date_field").type("2021-01-01", delay=CLICK_DELAY) - self.page.locator("#id_date_time_field").type("2021-01-01 01:01:00", delay=CLICK_DELAY) - self.page.locator("#id_decimal_field").type("0.123", delay=CLICK_DELAY) - self.page.locator("#id_duration_field").type("1", delay=CLICK_DELAY) - self.page.locator("#id_email_field").type("test@example.com", delay=CLICK_DELAY) - file_path_field_options = self.page.query_selector_all("#id_file_path_field option") - file_path_field_values: list[str] = [option.get_attribute("value") for option in file_path_field_options] - self.page.locator("#id_file_path_field").select_option(file_path_field_values[1]) - self.page.locator("#id_float_field").type("1.2345", delay=CLICK_DELAY) - self.page.locator("#id_generic_ip_address_field").type("127.0.0.1", delay=CLICK_DELAY) - self.page.locator("#id_integer_field").type("123", delay=CLICK_DELAY) - self.page.locator("#id_json_field").clear() - self.page.locator("#id_json_field").type('{"key": "value"}', delay=CLICK_DELAY) - self.page.locator("#id_multiple_choice_field").select_option(["2", "3"]) - self.page.locator("#id_null_boolean_field").select_option("false") - self.page.locator("#id_regex_field").type("12", delay=CLICK_DELAY) - self.page.locator("#id_slug_field").type("my-slug-text", delay=CLICK_DELAY) - self.page.locator("#id_time_field").type("01:01:00", delay=CLICK_DELAY) - self.page.locator("#id_typed_choice_field").select_option("2") - self.page.locator("#id_typed_multiple_choice_field").select_option(["1", "2"]) - self.page.locator("#id_url_field").type("http://example.com", delay=CLICK_DELAY) - self.page.locator("#id_uuid_field").type("550e8400-e29b-41d4-a716-446655440000", delay=CLICK_DELAY) - self.page.locator("#id_combo_field").type("test@example.com", delay=CLICK_DELAY) - self.page.locator("#id_password_field").type("password", delay=CLICK_DELAY) - - model_choice_field_options = self.page.query_selector_all("#id_model_multiple_choice_field option") - model_choice_field_values: list[str] = [option.get_attribute("value") for option in model_choice_field_options] - self.page.locator("#id_model_choice_field").select_option(model_choice_field_values[0]) - self.page.locator("#id_model_multiple_choice_field").select_option([ - model_choice_field_values[1], - model_choice_field_values[2], - ]) + # Submit and wait for one of the error messages to disappear (indicating that the form has been re-rendered) + invalid_feedback = self.page.locator(".invalid-feedback").all()[0] self.page.wait_for_selector("button[type=submit]").click(delay=CLICK_DELAY) - - # Wait for one of the error messages to disappear (indicating that the form has been re-rendered) - expect(self.page.locator(".invalid-feedback").all()[0]).not_to_be_attached() + expect(invalid_feedback).not_to_be_attached() # Make sure no errors remain assert len(self.page.query_selector_all(".invalid-feedback")) == 0 From 5993ffc762ce562f6f632577ba975a5e054d417e Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Thu, 13 Mar 2025 18:51:40 -0700 Subject: [PATCH 2/3] Better playwright logging --- tests/test_app/tests/utils.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/test_app/tests/utils.py b/tests/test_app/tests/utils.py index f1fb4bd9..dc3cb9dd 100644 --- a/tests/test_app/tests/utils.py +++ b/tests/test_app/tests/utils.py @@ -117,7 +117,16 @@ def start_playwright_client(cls): cls.browser = cls.playwright.chromium.launch(headless=bool(headless)) cls.page = cls.browser.new_page() cls.page.set_default_timeout(10000) - cls.page.on("console", lambda msg: _logger.error("error: %s", msg.text) if msg.type == "error" else None) + cls.page.on("console", cls.playwright_logging) + + @staticmethod + def playwright_logging(msg): + if msg.type == "error": + _logger.error(msg.text) + elif msg.type == "warning": + _logger.warning(msg.text) + elif msg.type == "info": + _logger.info(msg.text) @classmethod def shutdown_playwright_client(cls): From 911907e455508efc082374f803fbd8938068d9bb Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Thu, 13 Mar 2025 18:59:36 -0700 Subject: [PATCH 3/3] bump codeql version --- .github/workflows/codeql.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 17080b52..63a412e0 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -46,7 +46,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -59,7 +59,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # â„šī¸ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -72,6 +72,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy