diff --git a/Makefile b/Makefile
index 9f01ddaae9..239cf0ac3c 100644
--- a/Makefile
+++ b/Makefile
@@ -116,3 +116,8 @@ dev-compose-down-linux:
profile:
pipenv run python profile_application.py
+
+generate-integration-test:
+ pipenv run playwright install chromium
+ pipenv run python -m scripts.generate_integration_test
+ pipenv run black ./scripts/test_*
diff --git a/Pipfile b/Pipfile
index 1edd8c5a6a..07b6148af8 100644
--- a/Pipfile
+++ b/Pipfile
@@ -38,6 +38,7 @@ types-python-dateutil = "*"
pytest-mock = "*"
types-cachetools = "*"
types-pytz = "*"
+playwright = "*"
[packages]
colorama = "*"
diff --git a/Pipfile.lock b/Pipfile.lock
index ae499cb591..bf4b748975 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "b857953d9c0ba947a86596e0beb665969ae68afee425c3350a0dd4049a927daa"
+ "sha256": "408dbd7bc01df9a590c2f82b3818b9cc68d7e98e5f11b78350f75d87d706ee4c"
},
"pipfile-spec": 6,
"requires": {
@@ -43,20 +43,20 @@
},
"boto3": {
"hashes": [
- "sha256:300888f0c1b6f32f27f85a9aa876f50f46514ec619647af7e4d20db74d339714",
- "sha256:b26928f9a21cf3649cea20a59061340f3294c6e7785ceb6e1a953eb8010dc3ba"
+ "sha256:c26c31ceeeb2bc5d2bb96ba0fdc9a04d7b10e6e0b081c55b9cea9069a0be04dd",
+ "sha256:f8046e3e2d1186a49b49f7464c4811c265c86001f404dd1a96c4365c773a4245"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
- "version": "==1.34.56"
+ "version": "==1.34.57"
},
"botocore": {
"hashes": [
- "sha256:bffeb71ab21d47d4ecf947d9bdb2fbd1b0bbd0c27742cea7cf0b77b701c41d9f",
- "sha256:fff66e22a5589c2d58fba57d1d95c334ce771895e831f80365f6cff6453285ec"
+ "sha256:9a5aa2034de9f0c367b4b61a92af0fa827f5c21affa19e0a284838a142e71083",
+ "sha256:c8dafe0ad378a88bcf4153e6972870b03fb5aab406b694202307500709940baf"
],
"markers": "python_version >= '3.8'",
- "version": "==1.34.56"
+ "version": "==1.34.57"
},
"brotli": {
"hashes": [
@@ -608,12 +608,12 @@
},
"google-cloud-pubsub": {
"hashes": [
- "sha256:48c8e17a8168c43e3188635cbd9e07fbe3004120433712ce84b3a04bbf18c188",
- "sha256:8c69ed04800f4f552cdf3b9028f06d9271ac6e60443b2308c984def442e69684"
+ "sha256:06dd62181e2f248f32b9077f4dc07b413191a84fc06d7323b208602d887207bc",
+ "sha256:b6d06f1827968273c42b57a09f642462649c9504dc0f8756f99770f4e3e755ad"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
- "version": "==2.20.0"
+ "version": "==2.20.1"
},
"google-cloud-storage": {
"hashes": [
@@ -944,11 +944,11 @@
},
"jwcrypto": {
"hashes": [
- "sha256:59e7d5e4589d1b07170f368e20c32eb32a023911806a9723b1f43a0d8b3028d6",
- "sha256:c18b10b2049603bef3ae7b77ad14bded431a9077d113447d62bebd8550b0d5bd"
+ "sha256:150d2b0ebbdb8f40b77f543fb44ffd2baeff48788be71f67f03566692fd55789",
+ "sha256:771a87762a0c081ae6166958a954f80848820b2ab066937dc8b8379d65b1b039"
],
"markers": "python_version >= '3.8'",
- "version": "==1.5.5"
+ "version": "==1.5.6"
},
"markupsafe": {
"hashes": [
@@ -1534,20 +1534,20 @@
},
"boto3": {
"hashes": [
- "sha256:300888f0c1b6f32f27f85a9aa876f50f46514ec619647af7e4d20db74d339714",
- "sha256:b26928f9a21cf3649cea20a59061340f3294c6e7785ceb6e1a953eb8010dc3ba"
+ "sha256:c26c31ceeeb2bc5d2bb96ba0fdc9a04d7b10e6e0b081c55b9cea9069a0be04dd",
+ "sha256:f8046e3e2d1186a49b49f7464c4811c265c86001f404dd1a96c4365c773a4245"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
- "version": "==1.34.56"
+ "version": "==1.34.57"
},
"botocore": {
"hashes": [
- "sha256:bffeb71ab21d47d4ecf947d9bdb2fbd1b0bbd0c27742cea7cf0b77b701c41d9f",
- "sha256:fff66e22a5589c2d58fba57d1d95c334ce771895e831f80365f6cff6453285ec"
+ "sha256:9a5aa2034de9f0c367b4b61a92af0fa827f5c21affa19e0a284838a142e71083",
+ "sha256:c8dafe0ad378a88bcf4153e6972870b03fb5aab406b694202307500709940baf"
],
"markers": "python_version >= '3.8'",
- "version": "==1.34.56"
+ "version": "==1.34.57"
},
"certifi": {
"hashes": [
@@ -1913,6 +1913,70 @@
"markers": "python_version >= '3.7'",
"version": "==1.4.0"
},
+ "greenlet": {
+ "hashes": [
+ "sha256:01bc7ea167cf943b4c802068e178bbf70ae2e8c080467070d01bfa02f337ee67",
+ "sha256:0448abc479fab28b00cb472d278828b3ccca164531daab4e970a0458786055d6",
+ "sha256:086152f8fbc5955df88382e8a75984e2bb1c892ad2e3c80a2508954e52295257",
+ "sha256:098d86f528c855ead3479afe84b49242e174ed262456c342d70fc7f972bc13c4",
+ "sha256:149e94a2dd82d19838fe4b2259f1b6b9957d5ba1b25640d2380bea9c5df37676",
+ "sha256:1551a8195c0d4a68fac7a4325efac0d541b48def35feb49d803674ac32582f61",
+ "sha256:15d79dd26056573940fcb8c7413d84118086f2ec1a8acdfa854631084393efcc",
+ "sha256:1996cb9306c8595335bb157d133daf5cf9f693ef413e7673cb07e3e5871379ca",
+ "sha256:1a7191e42732df52cb5f39d3527217e7ab73cae2cb3694d241e18f53d84ea9a7",
+ "sha256:1ea188d4f49089fc6fb283845ab18a2518d279c7cd9da1065d7a84e991748728",
+ "sha256:1f672519db1796ca0d8753f9e78ec02355e862d0998193038c7073045899f305",
+ "sha256:2516a9957eed41dd8f1ec0c604f1cdc86758b587d964668b5b196a9db5bfcde6",
+ "sha256:2797aa5aedac23af156bbb5a6aa2cd3427ada2972c828244eb7d1b9255846379",
+ "sha256:2dd6e660effd852586b6a8478a1d244b8dc90ab5b1321751d2ea15deb49ed414",
+ "sha256:3ddc0f794e6ad661e321caa8d2f0a55ce01213c74722587256fb6566049a8b04",
+ "sha256:3ed7fb269f15dc662787f4119ec300ad0702fa1b19d2135a37c2c4de6fadfd4a",
+ "sha256:419b386f84949bf0e7c73e6032e3457b82a787c1ab4a0e43732898a761cc9dbf",
+ "sha256:43374442353259554ce33599da8b692d5aa96f8976d567d4badf263371fbe491",
+ "sha256:52f59dd9c96ad2fc0d5724107444f76eb20aaccb675bf825df6435acb7703559",
+ "sha256:57e8974f23e47dac22b83436bdcf23080ade568ce77df33159e019d161ce1d1e",
+ "sha256:5b51e85cb5ceda94e79d019ed36b35386e8c37d22f07d6a751cb659b180d5274",
+ "sha256:649dde7de1a5eceb258f9cb00bdf50e978c9db1b996964cd80703614c86495eb",
+ "sha256:64d7675ad83578e3fc149b617a444fab8efdafc9385471f868eb5ff83e446b8b",
+ "sha256:68834da854554926fbedd38c76e60c4a2e3198c6fbed520b106a8986445caaf9",
+ "sha256:6b66c9c1e7ccabad3a7d037b2bcb740122a7b17a53734b7d72a344ce39882a1b",
+ "sha256:70fb482fdf2c707765ab5f0b6655e9cfcf3780d8d87355a063547b41177599be",
+ "sha256:7170375bcc99f1a2fbd9c306f5be8764eaf3ac6b5cb968862cad4c7057756506",
+ "sha256:73a411ef564e0e097dbe7e866bb2dda0f027e072b04da387282b02c308807405",
+ "sha256:77457465d89b8263bca14759d7c1684df840b6811b2499838cc5b040a8b5b113",
+ "sha256:7f362975f2d179f9e26928c5b517524e89dd48530a0202570d55ad6ca5d8a56f",
+ "sha256:81bb9c6d52e8321f09c3d165b2a78c680506d9af285bfccbad9fb7ad5a5da3e5",
+ "sha256:881b7db1ebff4ba09aaaeae6aa491daeb226c8150fc20e836ad00041bcb11230",
+ "sha256:894393ce10ceac937e56ec00bb71c4c2f8209ad516e96033e4b3b1de270e200d",
+ "sha256:99bf650dc5d69546e076f413a87481ee1d2d09aaaaaca058c9251b6d8c14783f",
+ "sha256:9da2bd29ed9e4f15955dd1595ad7bc9320308a3b766ef7f837e23ad4b4aac31a",
+ "sha256:afaff6cf5200befd5cec055b07d1c0a5a06c040fe5ad148abcd11ba6ab9b114e",
+ "sha256:b1b5667cced97081bf57b8fa1d6bfca67814b0afd38208d52538316e9422fc61",
+ "sha256:b37eef18ea55f2ffd8f00ff8fe7c8d3818abd3e25fb73fae2ca3b672e333a7a6",
+ "sha256:b542be2440edc2d48547b5923c408cbe0fc94afb9f18741faa6ae970dbcb9b6d",
+ "sha256:b7dcbe92cc99f08c8dd11f930de4d99ef756c3591a5377d1d9cd7dd5e896da71",
+ "sha256:b7f009caad047246ed379e1c4dbcb8b020f0a390667ea74d2387be2998f58a22",
+ "sha256:bba5387a6975598857d86de9eac14210a49d554a77eb8261cc68b7d082f78ce2",
+ "sha256:c5e1536de2aad7bf62e27baf79225d0d64360d4168cf2e6becb91baf1ed074f3",
+ "sha256:c5ee858cfe08f34712f548c3c363e807e7186f03ad7a5039ebadb29e8c6be067",
+ "sha256:c9db1c18f0eaad2f804728c67d6c610778456e3e1cc4ab4bbd5eeb8e6053c6fc",
+ "sha256:d353cadd6083fdb056bb46ed07e4340b0869c305c8ca54ef9da3421acbdf6881",
+ "sha256:d46677c85c5ba00a9cb6f7a00b2bfa6f812192d2c9f7d9c4f6a55b60216712f3",
+ "sha256:d4d1ac74f5c0c0524e4a24335350edad7e5f03b9532da7ea4d3c54d527784f2e",
+ "sha256:d73a9fe764d77f87f8ec26a0c85144d6a951a6c438dfe50487df5595c6373eac",
+ "sha256:da70d4d51c8b306bb7a031d5cff6cc25ad253affe89b70352af5f1cb68e74b53",
+ "sha256:daf3cb43b7cf2ba96d614252ce1684c1bccee6b2183a01328c98d36fcd7d5cb0",
+ "sha256:dca1e2f3ca00b84a396bc1bce13dd21f680f035314d2379c4160c98153b2059b",
+ "sha256:dd4f49ae60e10adbc94b45c0b5e6a179acc1736cf7a90160b404076ee283cf83",
+ "sha256:e1f145462f1fa6e4a4ae3c0f782e580ce44d57c8f2c7aae1b6fa88c0b2efdb41",
+ "sha256:e3391d1e16e2a5a1507d83e4a8b100f4ee626e8eca43cf2cadb543de69827c4c",
+ "sha256:fcd2469d6a2cf298f198f0487e0a5b1a47a42ca0fa4dfd1b6862c999f018ebbf",
+ "sha256:fd096eb7ffef17c456cfa587523c5f92321ae02427ff955bebe9e3c63bc9f0da",
+ "sha256:fe754d231288e1e64323cfad462fcee8f0288654c10bdf4f603a39ed923bef33"
+ ],
+ "markers": "python_version >= '3.11' and platform_python_implementation == 'CPython'",
+ "version": "==3.0.3"
+ },
"httmock": {
"hashes": [
"sha256:13e6c63f135a928e15d386af789a2890efb03e0e280f29bdc9961f3f0dc34cb9",
@@ -2197,6 +2261,20 @@
"markers": "python_version >= '3.8'",
"version": "==4.2.0"
},
+ "playwright": {
+ "hashes": [
+ "sha256:283887f0bdd0039c3d720e32fbc73a045c24fa800599a6ad60fb199c29580534",
+ "sha256:313f2551a772f57c9ccca017c4dd4661f2277166f9e1d84bbf5a2e316f0f892c",
+ "sha256:4e1fc1c049a0af64626ddd50814d14a01f316bcbb4d1aa83c3416fe420add558",
+ "sha256:b2a46a24641e5d468046cde567c98fdb8d85e32df901630b14dfb288cbd1ed4f",
+ "sha256:dbf473496808d4c2c816902c1dee2aabc029648e56ce8514b643f5a1a6fc8e22",
+ "sha256:e092c6cfbf797bff03fbdfc53c3e6a9e29fbcf6b82f9e43113d37494aee0561b",
+ "sha256:e2b293f077efeaa45253fde31cea4bc6b0ae8be6b5e65e8ce8b4aa3b9f0d55b6"
+ ],
+ "index": "pypi",
+ "markers": "python_version >= '3.8'",
+ "version": "==1.42.0"
+ },
"pluggy": {
"hashes": [
"sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981",
@@ -2220,6 +2298,14 @@
],
"version": "==2.21"
},
+ "pyee": {
+ "hashes": [
+ "sha256:9bcc9647822234f42c228d88de63d0f9ffa881e87a87f9d36ddf5211f6ac977d",
+ "sha256:a642c51e3885a33ead087286e35212783a4e9b8d6514a10a5db4e57ac57b2b29"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==11.0.1"
+ },
"pyflakes": {
"hashes": [
"sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f",
diff --git a/README.md b/README.md
index 46975c88cf..c700ff6c37 100644
--- a/README.md
+++ b/README.md
@@ -194,6 +194,11 @@ Or set the `GOOGLE_CLOUD_PROJECT` environment variable to your gcp project id.
---
+
+## Integration Tests
+There is a dev-convenience script that auto generates the lines of code for a user journey. See [README](scripts/README.md) for more information and how to run
+the script.
+
## Frontend Tests
The frontend tests use NodeJS to run. To handle different versions of NodeJS it is recommended to install `Node Version Manager` (`nvm`). It is similar to pyenv but for Node versions.
diff --git a/app/translations/messages.pot b/app/translations/messages.pot
index 700a61f344..fa30249d65 100644
--- a/app/translations/messages.pot
+++ b/app/translations/messages.pot
@@ -249,55 +249,55 @@ msgid_plural "{number_of_days} days"
msgstr[0] ""
msgstr[1] ""
-#: app/routes/errors.py:159
+#: app/routes/errors.py:160
msgid "You have reached the maximum number of individual access codes"
msgstr ""
-#: app/routes/errors.py:162
+#: app/routes/errors.py:163
msgid ""
"If you need more individual access codes, please contact us."
msgstr ""
-#: app/routes/errors.py:180
+#: app/routes/errors.py:181
msgid "You have reached the maximum number of times for submitting feedback"
msgstr ""
-#: app/routes/errors.py:183
+#: app/routes/errors.py:184
msgid ""
"If you need to give more feedback, please contact us."
msgstr ""
-#: app/routes/errors.py:233
+#: app/routes/errors.py:232
msgid "Sorry, there was a problem sending the access code"
msgstr ""
-#: app/routes/errors.py:240
+#: app/routes/errors.py:239
msgid "You can try to request a new access code again."
msgstr ""
-#: app/routes/errors.py:243 app/routes/errors.py:268 app/routes/errors.py:290
+#: app/routes/errors.py:242 app/routes/errors.py:267 app/routes/errors.py:289
msgid ""
"If this problem keeps happening, please contact us for help."
msgstr ""
-#: app/routes/errors.py:264
+#: app/routes/errors.py:263
msgid "Sorry, there was a problem sending the confirmation email"
msgstr ""
-#: app/routes/errors.py:265
+#: app/routes/errors.py:264
msgid "You can try to send the email again."
msgstr ""
-#: app/routes/errors.py:286 templates/errors/403.html:3
+#: app/routes/errors.py:285 templates/errors/403.html:3
#: templates/errors/403.html:6 templates/errors/submission-failed.html:5
#: templates/errors/submission-failed.html:8
msgid "Sorry, there is a problem"
msgstr ""
-#: app/routes/errors.py:287
+#: app/routes/errors.py:286
msgid "You can try to submit your feedback again."
msgstr ""
diff --git a/mypy.ini b/mypy.ini
index 8918828886..0e98cd508a 100644
--- a/mypy.ini
+++ b/mypy.ini
@@ -106,3 +106,8 @@ no_implicit_optional = True
disallow_untyped_defs = True
warn_return_any = True
no_implicit_optional = True
+
+[mypy-scripts.generate_integration_test]
+disallow_untyped_defs = True
+warn_return_any = True
+no_implicit_optional = True
diff --git a/scripts/README.md b/scripts/README.md
new file mode 100644
index 0000000000..0d055d48bb
--- /dev/null
+++ b/scripts/README.md
@@ -0,0 +1,40 @@
+# Scripts
+
+## Script to auto-generate code for integration test
+
+### Details
+
+To speed up the process of generating integration tests for Runner, there is a dev-convenience script that records the GET and POST requests of a user journey
+and outputs this formatted in the style of an integration test.
+
+### Overview
+
+* All POSTs are recorded. To ensure only the necessary GET requests are recorded, additional logic excludes the following GET requests:
+ * Session tokens
+ * Initial URL requests for each page load
+* Additional logic is in place to ensure that, when navigating backwards in a journey after following links (e.g. 'previous' link), it is recorded correctly.
+ This is achieved by storing the previous request method at module-level so that it can be used in deciding whether to record or disregard the GET request.
+* You will need to manually add your assertions in the generated test file
+* When the script is launched, it will create a new file for the schema chosen. If you launch the script again for the same schema, it will overwrite the
+ previous file output
+* The script is intended to be run with schemas with a `test_` prefix, which would suit most scenarios for test generation. If you wish to use a schema without
+ this prefix, you will need to manually amend the generated names for the file, class, and function to allow pytest to process the test file correctly
+* It does **not** handle dynamic answers because these are generated at runtime - you will need to update the output script to handle `list_item_id` separately,
+ as they will not be known beforehand
+
+### Usage
+
+Run the following make command from the project root folder:
+
+```shell
+make generate-integration-test
+```
+
+This will pause the script and open a browser pointing to the Launcher UI (make sure the application and supporting services are running). Now follow the below
+steps:
+
+1. Choose a schema and launch it - the schema name will be used for the name of the integration test output file
+1. Navigate through the survey
+1. When you're finished with the journey at any point, return to the command line and hit Enter
+1. The output will be shown in the logs, and a formatted file will be created for you in the scripts folder. For example: `scripts/test_checkbox.py`
+1. Add your assertions to the test file and move the file into the appropriate `test/integration/` location
diff --git a/scripts/generate_integration_test.py b/scripts/generate_integration_test.py
new file mode 100644
index 0000000000..449bd4997c
--- /dev/null
+++ b/scripts/generate_integration_test.py
@@ -0,0 +1,146 @@
+from typing import IO, Dict
+from urllib.parse import parse_qs, urlparse
+
+from playwright.sync_api import Playwright, Request, sync_playwright
+from structlog import get_logger
+
+logger = get_logger()
+
+LAUNCHER_ROOT_URL = "http://localhost:8000"
+RUNNER_ROOT_URL = "http://localhost:5000"
+
+TEST_TEMPLATE = """from tests.integration.integration_test_case import IntegrationTestCase
+
+
+class Test{class_name}(IntegrationTestCase):
+ def test_{function_name}(self):
+ self.launchSurvey("{schema_name}")
+"""
+
+survey_journey: Dict[str, str | bool | None] = {
+ "previous_request_method": None,
+ "in_progress": False,
+ "schema_name": None,
+}
+
+output: Dict[str, str] = {"file_name": ""}
+
+
+def process_runner_request(request: Request) -> None:
+ with open(output["file_name"], "a", encoding="utf-8") as file:
+ if request.method == "POST":
+ process_post(request, file)
+
+ elif request.method == "GET":
+ process_get(request, file)
+
+
+def process_post(request: Request, file: IO) -> None:
+ survey_journey["previous_request_method"] = "POST"
+
+ # Playwright Request.post_data comes formatted like a URL query string, so can be parsed
+ post_data = parse_qs(request.post_data)
+ del post_data["csrf_token"]
+
+ items = {
+ answer_id: answer_values[0] if len(answer_values) == 1 else answer_values
+ for answer_id, answer_values in post_data.items()
+ }
+
+ # Post items, or empty post for no answers/non-question pages
+ file.write(generate_method_request(method="post", data=items or ""))
+
+
+def is_recordable_survey_navigation(request: Request) -> bool:
+ return (
+ survey_journey["previous_request_method"] == "GET"
+ and "session?token" not in request.url
+ and request.url != f"{RUNNER_ROOT_URL}/questionnaire/"
+ )
+
+
+def process_get(request: Request, file: IO) -> None:
+ """
+ We only want to record GET requests in Runner for actions like navigating back in a survey journey. Therefore, we exclude the following:
+ - the very first GET action of a survey journey, after schema is loaded
+ - tokens/authentication
+ """
+ has_journey_started = (
+ not survey_journey["in_progress"]
+ and request.url == f"{RUNNER_ROOT_URL}/questionnaire/"
+ )
+ if has_journey_started:
+ survey_journey["in_progress"] = True
+ return
+
+ if is_recordable_survey_navigation(request):
+ path = f'"{urlparse(request.url).path}"'
+ file.write(generate_method_request(method="get", data=path))
+
+ elif survey_journey["in_progress"]:
+ # ensure the request method is captured - allows us to record Runner GET navigation actions on the next pass through
+ survey_journey["previous_request_method"] = request.method
+
+
+def process_launcher_request(request: Request) -> None:
+ if request.method != "GET":
+ return
+
+ if survey_journey["in_progress"]:
+ # capture launcher urls for sign-out, save etc
+ with open(output["file_name"], "a", encoding="utf-8") as file:
+ path = f'"{urlparse(request.url).path}"'
+ file.write(generate_method_request(method="get", data=path))
+ else:
+ # start of journey, so create a skeleton file using the schema name
+ survey_journey["schema_name"] = parse_qs(request.url)["schema_name"][0]
+ output["file_name"] = f"./scripts/{survey_journey['schema_name']}.py"
+
+ with open(output["file_name"], "w", encoding="utf-8") as file:
+ # Type ignore: schema_name is taken as string from query string
+ class_name = survey_journey["schema_name"].title().replace("_", "") # type: ignore
+ file.write(
+ TEST_TEMPLATE.format(
+ class_name=class_name,
+ function_name=survey_journey["schema_name"],
+ schema_name=survey_journey["schema_name"],
+ )
+ )
+ logger.info(request)
+
+
+def generate_method_request(*, method: str, data: dict | str | None = None) -> str:
+ snippet = f"self.{method}({data})"
+ logger.info(f'Generating Runner code snippet for HTTP request: "{snippet}"')
+ return f"\n {snippet}"
+
+
+def request_handler(request: Request) -> None:
+ if LAUNCHER_ROOT_URL in request.url:
+ process_launcher_request(request)
+ elif RUNNER_ROOT_URL in request.url:
+ process_runner_request(request)
+
+
+def run(pw: Playwright) -> None:
+ chromium = pw.chromium
+ browser = chromium.launch(headless=False, args=["--start-maximized"])
+ page = browser.new_page(no_viewport=True)
+ page.goto(LAUNCHER_ROOT_URL)
+
+ page.on("request", request_handler)
+
+ input(
+ "Script is paused. Start navigating through the browser for the journey & press Enter when finished to capture"
+ " the output and add into a test file\n"
+ )
+ browser.close()
+ logger.info(
+ "Integration test generated successfully",
+ integration_test_file=output["file_name"],
+ )
+
+
+if __name__ == "__main__":
+ with sync_playwright() as playwright:
+ run(playwright)
diff --git a/scripts/merge_profiles.py b/scripts/merge_profiles.py
index 4f5c4e6ea3..452bb27c59 100644
--- a/scripts/merge_profiles.py
+++ b/scripts/merge_profiles.py
@@ -15,4 +15,5 @@
else:
stats.add(profiling_dir + p)
-stats.dump_stats("combined_profile.prof")
+if stats:
+ stats.dump_stats("combined_profile.prof")
diff --git a/scripts/run_mypy.sh b/scripts/run_mypy.sh
index d3bdb34e1e..27a4f3ec42 100755
--- a/scripts/run_mypy.sh
+++ b/scripts/run_mypy.sh
@@ -1,3 +1,3 @@
#!/usr/bin/env bash
-pipenv run mypy app
+pipenv run mypy app scripts
diff --git a/tests/integration/test_header_links.py b/tests/integration/test_header_links.py
index 92a11ff9fc..72d81f5053 100644
--- a/tests/integration/test_header_links.py
+++ b/tests/integration/test_header_links.py
@@ -165,7 +165,7 @@ def test_links_not_in_header_when_no_session(self):
self.assert_sign_out_link_does_not_exist()
self.assert_help_link_does_not_exist()
- def test_links_not_in_header_when_valid_session_theme_social(self):
+ def test_links_not_in_header_when_valid_session_theme_social_thank_you_page(self):
# Given
self.launchSurveyV2(schema_name="test_theme_social", theme="social")
self.post()