From 83af639a8a337041073a8bc37d3d1a5fd9870172 Mon Sep 17 00:00:00 2001 From: antuarc Date: Fri, 13 Dec 2024 14:23:00 +1000 Subject: [PATCH] [QOLSVC-8587] sync tests with Open Data theme --- .ahoy.yml | 14 ++- .docker/test.ini | 1 + .github/workflows/test.yml | 18 ++-- bin/build.sh | 2 +- bin/create-test-data.sh | 3 +- dev-requirements-2.9-py2.txt | 14 +-- dev-requirements-2.9.txt | 14 +-- dev-requirements.txt | 14 +-- test/features/admin_reporting.feature | 1 + test/features/comments.feature | 9 +- test/features/data_qld_theme.feature | 7 ++ test/features/data_usability_rating.feature | 15 +++- test/features/data_validation.feature | 1 + test/features/datarequest.feature | 56 ++++++++++++ .../datarequest_circumstances.feature | 1 + test/features/dataset_schema.feature | 1 + test/features/datasets.feature | 7 +- test/features/engagement_reporting.feature | 23 ++--- test/features/environment.py | 1 + test/features/groups.feature | 31 ++++++- test/features/organisations.feature | 32 ++++++- test/features/reporting.feature | 33 ++++++- test/features/resource_freshness.feature | 14 +-- test/features/schema_generation.feature | 1 + test/features/steps/steps.py | 87 +++++++++++++++---- 25 files changed, 309 insertions(+), 91 deletions(-) diff --git a/.ahoy.yml b/.ahoy.yml index 0ed39bf..6cfa604 100644 --- a/.ahoy.yml +++ b/.ahoy.yml @@ -144,22 +144,20 @@ commands: ahoy cli "rm -f test/screenshots/*" ahoy start-ckan-job-workers ahoy start-mailmock & - sleep 5 && + sleep 5 if [ "$BEHAVE_TAG" = "" ]; then # no tag specified, probably running locally - # Run reporting tests last so numbers are consistent (ahoy cli "behave -k ${*:-test/features} --tags=smoke" \ - && ahoy cli "behave -k ${*:-test/features} --tags=-smoke --tags=-reporting" \ - && ahoy cli "behave -k ${*:-test/features} --tags=reporting" \ + && ahoy cli "behave -k ${*:-test/features} --tags=-smoke" \ ) || [ "${ALLOW_BDD_FAIL:-0}" -eq 1 ] elif [ "$BEHAVE_TAG" = "authenticated" ]; then # run any tests that don't have a specific tag - ahoy cli "behave -k ${*:-test/features} --tags=-unauthenticated --tags=-smoke --tags=-reporting" \ + ahoy cli "behave -k ${*:-test/features} --tags=-unauthenticated --tags=-smoke --tags=-OpenData --tags=-multi_plugin" \ || [ "${ALLOW_BDD_FAIL:-0}" -eq 1 ] - # Run reporting tests last so numbers are consistent - ahoy cli "behave -k ${*:-test/features} --tags=reporting" || \ - [ "${ALLOW_BDD_FAIL:-0}" -eq 1 ] else + if [ "$BEHAVE_TAG" != "multi_plugin" ]; then + BEHAVE_TAG="$BEHAVE_TAG --tags=-multi_plugin" + fi # run tests with the specified tag ahoy cli "behave -k ${*:-test/features} --tags=$BEHAVE_TAG" \ || [ "${ALLOW_BDD_FAIL:-0}" -eq 1 ] diff --git a/.docker/test.ini b/.docker/test.ini index 1850d13..b630b21 100644 --- a/.docker/test.ini +++ b/.docker/test.ini @@ -56,6 +56,7 @@ ckan.datastore.default_fts_index_method = gist ## Site Settings. ckan.site_url = http://ckan:5000/ +WTF_CSRF_ENABLED = False ## Authorization Settings diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f7a0c57..7b8a1ce 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,8 +12,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 5 steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: '3.x' - name: Install requirements @@ -26,18 +26,22 @@ jobs: strategy: fail-fast: true matrix: - ckan-version: ["2.10", 2.9, 2.9-py2] - behave-tag: [smoke, authenticated, unauthenticated] + ckan-version: ["2.10", 2.9] + behave-tag: [smoke, unauthenticated, multi_plugin, OpenData, authenticated] name: Run ${{ matrix.behave-tag }} tests on CKAN ${{ matrix.ckan-version }} runs-on: ubuntu-latest - container: drevops/ci-builder:23.7.0 + container: drevops/ci-runner:23.12.0 env: CKAN_VERSION: ${{ matrix.ckan-version }} BEHAVE_TAG: ${{ matrix.behave-tag }} steps: - - uses: actions/checkout@v3 + # Patch https://github.com/actions/runner/issues/863 + - name: Preserve $HOME set in the container + run: echo HOME=/root >> "$GITHUB_ENV" + + - uses: actions/checkout@v4 timeout-minutes: 2 - name: Build @@ -65,7 +69,7 @@ jobs: - name: Upload screenshots if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: CKAN ${{ matrix.ckan-version }} ${{ matrix.behave-tag }} screenshots path: /tmp/artifacts/behave/screenshots diff --git a/bin/build.sh b/bin/build.sh index e17b0e5..3c907b0 100755 --- a/bin/build.sh +++ b/bin/build.sh @@ -20,7 +20,7 @@ CKAN_GIT_VERSION=$CKAN_VERSION CKAN_GIT_ORG=qld-gov-au if [ "$CKAN_VERSION" = "2.10" ]; then - CKAN_GIT_VERSION=ckan-2.10.1-qgov.4 + CKAN_GIT_VERSION=ckan-2.10.5-qgov.4 PYTHON_VERSION=py3 PYTHON="${PYTHON}3" else diff --git a/bin/create-test-data.sh b/bin/create-test-data.sh index 7f17c87..a34e671 100644 --- a/bin/create-test-data.sh +++ b/bin/create-test-data.sh @@ -118,10 +118,11 @@ curl -LsH "Authorization: ${API_KEY}" \ "license_id": "other-open", "data_driven_application": "NO", "security_classification": "PUBLIC", "notes": "public test", "de_identified_data": "NO", "resources": [ {"name": "test-resource", "description": "Test resource description", - "url": "https://example.com", "format": "HTML", "size": 1024} + "url": "https://example.com/foo", "format": "HTML", "size": 1024} ]}' \ ${CKAN_ACTION_URL}/package_create +ckan_cli archiver update-test public-test-dataset # Datasets need to be assigned to an organisation echo "Assigning test Datasets to Organisation..." diff --git a/dev-requirements-2.9-py2.txt b/dev-requirements-2.9-py2.txt index 8e0ba18..7dec48a 100644 --- a/dev-requirements-2.9-py2.txt +++ b/dev-requirements-2.9-py2.txt @@ -17,18 +17,18 @@ progressbar==2.5 -e git+https://github.com/ckan/ckanext-dcat.git@v1.2.0#egg=ckanext-dcat -e git+https://github.com/ckan/ckanext-scheming.git@release-3.0.0#egg=ckanext-scheming --e git+https://github.com/qld-gov-au/ckanext-archiver.git@2.1.1-qgov.15#egg=ckanext-archiver --e git+https://github.com/qld-gov-au/ckanext-csrf-filter.git@1.1.8#egg=ckanext-csrf-filter --e git+https://github.com/qld-gov-au/ckanext-data-qld.git@7.2.3#egg=ckanext-data-qld --e git+https://github.com/qld-gov-au/ckanext-datarequests.git@2.2.1-qgov.9#egg=ckanext-datarequests +-e git+https://github.com/qld-gov-au/ckanext-archiver.git@2.1.1-qgov.16#egg=ckanext-archiver +-e git+https://github.com/qld-gov-au/ckanext-csrf-filter.git@1.2.1#egg=ckanext-csrf-filter +-e git+https://github.com/qld-gov-au/ckanext-data-qld.git@7.3.1#egg=ckanext-data-qld +-e git+https://github.com/qld-gov-au/ckanext-datarequests.git@2.2.1-qgov.11#egg=ckanext-datarequests -e git+https://github.com/qld-gov-au/ckanext-harvest.git@v1.4.2.a#egg=ckanext-harvest --e git+https://github.com/qld-gov-au/ckanext-qa.git@2.0.3-qgov.9#egg=ckanext-qa +-e git+https://github.com/qld-gov-au/ckanext-qa.git@2.0.3-qgov.10#egg=ckanext-qa -e git+https://github.com/qld-gov-au/ckanext-qgov.git@6.0.2#egg=ckanext-qgov -e git+https://github.com/qld-gov-au/ckanext-report.git@0.3.1-qgov.2#egg=ckanext-report --e git+https://github.com/qld-gov-au/ckanext-resource-type-validation.git@1.0.5#egg=ckanext-resource-type-validation +-e git+https://github.com/qld-gov-au/ckanext-resource-type-validation.git@1.0.7#egg=ckanext-resource-type-validation -e git+https://github.com/qld-gov-au/ckanext-ssm-config.git@0.0.2#egg=ckanext-ssm-config -e git+https://github.com/qld-gov-au/ckanext-validation.git@v0.0.8-qgov.11#egg=ckanext-validation -e git+https://github.com/qld-gov-au/ckanext-xloader.git@1.0.1-qgov.4#egg=ckanext-xloader --e git+https://github.com/qld-gov-au/ckanext-ytp-comments.git@2.5.0-qgov.15#egg=ckanext-ytp-comments +-e git+https://github.com/qld-gov-au/ckanext-ytp-comments.git@2.5.0-qgov.16#egg=ckanext-ytp-comments -e git+https://github.com/qld-gov-au/ckanext-resource-visibility.git@2.1.1#egg=ckanext-resource-visibility -e git+https://github.com/qld-gov-au/ckanext-validation-schema-generator.git@develop#egg=ckanext-validation-schema-generator diff --git a/dev-requirements-2.9.txt b/dev-requirements-2.9.txt index 4356d9c..4e69360 100644 --- a/dev-requirements-2.9.txt +++ b/dev-requirements-2.9.txt @@ -15,18 +15,18 @@ progressbar==2.5 -e git+https://github.com/ckan/ckanext-dcat.git@v1.2.0#egg=ckanext-dcat -e git+https://github.com/ckan/ckanext-scheming.git@release-3.0.0#egg=ckanext-scheming --e git+https://github.com/qld-gov-au/ckanext-archiver.git@2.1.1-qgov.15#egg=ckanext-archiver --e git+https://github.com/qld-gov-au/ckanext-csrf-filter.git@1.1.8#egg=ckanext-csrf-filter --e git+https://github.com/qld-gov-au/ckanext-data-qld.git@7.2.3#egg=ckanext-data-qld --e git+https://github.com/qld-gov-au/ckanext-datarequests.git@2.2.1-qgov.9#egg=ckanext-datarequests +-e git+https://github.com/qld-gov-au/ckanext-archiver.git@2.1.1-qgov.16#egg=ckanext-archiver +-e git+https://github.com/qld-gov-au/ckanext-csrf-filter.git@1.2.1#egg=ckanext-csrf-filter +-e git+https://github.com/qld-gov-au/ckanext-data-qld.git@7.3.1#egg=ckanext-data-qld +-e git+https://github.com/qld-gov-au/ckanext-datarequests.git@2.2.1-qgov.11#egg=ckanext-datarequests -e git+https://github.com/qld-gov-au/ckanext-harvest.git@v1.4.2.a#egg=ckanext-harvest --e git+https://github.com/qld-gov-au/ckanext-qa.git@2.0.3-qgov.9#egg=ckanext-qa +-e git+https://github.com/qld-gov-au/ckanext-qa.git@2.0.3-qgov.10#egg=ckanext-qa -e git+https://github.com/qld-gov-au/ckanext-qgov.git@6.0.2#egg=ckanext-qgov -e git+https://github.com/qld-gov-au/ckanext-report.git@0.3.1-qgov.2#egg=ckanext-report --e git+https://github.com/qld-gov-au/ckanext-resource-type-validation.git@1.0.5#egg=ckanext-resource-type-validation +-e git+https://github.com/qld-gov-au/ckanext-resource-type-validation.git@1.0.7#egg=ckanext-resource-type-validation -e git+https://github.com/qld-gov-au/ckanext-ssm-config.git@0.0.2#egg=ckanext-ssm-config -e git+https://github.com/qld-gov-au/ckanext-validation.git@v0.0.8-qgov.11#egg=ckanext-validation -e git+https://github.com/qld-gov-au/ckanext-xloader.git@1.0.1-qgov.4#egg=ckanext-xloader --e git+https://github.com/qld-gov-au/ckanext-ytp-comments.git@2.5.0-qgov.15#egg=ckanext-ytp-comments +-e git+https://github.com/qld-gov-au/ckanext-ytp-comments.git@2.5.0-qgov.16#egg=ckanext-ytp-comments -e git+https://github.com/qld-gov-au/ckanext-resource-visibility.git@2.1.1#egg=ckanext-resource-visibility -e git+https://github.com/qld-gov-au/ckanext-validation-schema-generator.git@develop#egg=ckanext-validation-schema-generator diff --git a/dev-requirements.txt b/dev-requirements.txt index bfd41fc..cd02de9 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -15,18 +15,18 @@ progressbar==2.5 -e git+https://github.com/ckan/ckanext-dcat.git@v1.2.0#egg=ckanext-dcat -e git+https://github.com/ckan/ckanext-scheming.git@release-3.0.0#egg=ckanext-scheming --e git+https://github.com/qld-gov-au/ckanext-archiver.git@2.1.1-qgov.15#egg=ckanext-archiver --e git+https://github.com/qld-gov-au/ckanext-csrf-filter.git@1.1.8#egg=ckanext-csrf-filter --e git+https://github.com/qld-gov-au/ckanext-data-qld.git@7.2.3#egg=ckanext-data-qld --e git+https://github.com/qld-gov-au/ckanext-datarequests.git@2.2.1-qgov.9#egg=ckanext-datarequests +-e git+https://github.com/qld-gov-au/ckanext-archiver.git@2.1.1-qgov.16#egg=ckanext-archiver +-e git+https://github.com/qld-gov-au/ckanext-csrf-filter.git@1.2.1#egg=ckanext-csrf-filter +-e git+https://github.com/qld-gov-au/ckanext-data-qld.git@7.3.1#egg=ckanext-data-qld +-e git+https://github.com/qld-gov-au/ckanext-datarequests.git@2.2.1-qgov.11#egg=ckanext-datarequests -e git+https://github.com/qld-gov-au/ckanext-harvest.git@v1.4.2.a#egg=ckanext-harvest --e git+https://github.com/qld-gov-au/ckanext-qa.git@2.0.3-qgov.9#egg=ckanext-qa +-e git+https://github.com/qld-gov-au/ckanext-qa.git@2.0.3-qgov.10#egg=ckanext-qa -e git+https://github.com/qld-gov-au/ckanext-qgov.git@6.0.2#egg=ckanext-qgov -e git+https://github.com/qld-gov-au/ckanext-report.git@0.3.1-qgov.2#egg=ckanext-report --e git+https://github.com/qld-gov-au/ckanext-resource-type-validation.git@1.0.5#egg=ckanext-resource-type-validation +-e git+https://github.com/qld-gov-au/ckanext-resource-type-validation.git@1.0.7#egg=ckanext-resource-type-validation -e git+https://github.com/qld-gov-au/ckanext-ssm-config.git@0.0.2#egg=ckanext-ssm-config -e git+https://github.com/qld-gov-au/ckanext-validation.git@v0.0.8-qgov.11#egg=ckanext-validation -e git+https://github.com/qld-gov-au/ckanext-xloader.git@1.0.1-qgov.4#egg=ckanext-xloader --e git+https://github.com/qld-gov-au/ckanext-ytp-comments.git@2.5.0-qgov.15#egg=ckanext-ytp-comments +-e git+https://github.com/qld-gov-au/ckanext-ytp-comments.git@2.5.0-qgov.16#egg=ckanext-ytp-comments -e git+https://github.com/qld-gov-au/ckanext-resource-visibility.git@2.1.1#egg=ckanext-resource-visibility -e git+https://github.com/qld-gov-au/ckanext-validation-schema-generator.git@develop#egg=ckanext-validation-schema-generator diff --git a/test/features/admin_reporting.feature b/test/features/admin_reporting.feature index 512c30a..ad9d63e 100644 --- a/test/features/admin_reporting.feature +++ b/test/features/admin_reporting.feature @@ -1,5 +1,6 @@ @reporting @OpenData +@multi_plugin Feature: AdminReporting Scenario: As an admin user of my organisation, I can view 'My Reports' tab in the dashboard and show the 'Admin Report' with filters and table columns diff --git a/test/features/comments.feature b/test/features/comments.feature index d29d146..fa8b7b4 100644 --- a/test/features/comments.feature +++ b/test/features/comments.feature @@ -1,5 +1,6 @@ @comments @OpenData +@multi_plugin Feature: Comments @unauthenticated @@ -30,7 +31,7 @@ Feature: Comments @comment-add @datarequest Scenario: When a logged-in user submits a comment on a Data Request the comment should then be visible on the Comments tab of the Data Request - Given "CKANUser" as the persona + Given "TestOrgEditor" as the persona When I log in And I create a datarequest And I go to data request "$last_generated_title" comments @@ -40,7 +41,7 @@ Feature: Comments @comment-add @datarequest @email Scenario: When a logged-in user submits a comment on a Data Request the email should contain title and comment - Given "CKANUser" as the persona + Given "TestOrgEditor" as the persona When I log in And I create a datarequest And I go to data request "$last_generated_title" comments @@ -71,7 +72,7 @@ Feature: Comments @comment-add @comment-profane @datarequest Scenario: When a logged-in user submits a comment containing profanity on a Data Request they should receive an error message and the comment will not appear - Given "CKANUser" as the persona + Given "TestOrgEditor" as the persona When I log in And I create a datarequest And I go to data request "$last_generated_title" comments @@ -96,7 +97,7 @@ Feature: Comments @comment-report @datarequest @email Scenario: When a logged-in user reports a comment on a Data Request the comment should be marked as reported and an email notification sent to the organisation admins - Given "CKANUser" as the persona + Given "TestOrgEditor" as the persona When I log in And I create a datarequest And I go to data request "$last_generated_title" comments diff --git a/test/features/data_qld_theme.feature b/test/features/data_qld_theme.feature index 5b38f11..bd7f72c 100644 --- a/test/features/data_qld_theme.feature +++ b/test/features/data_qld_theme.feature @@ -129,3 +129,10 @@ Feature: Theme customisations When I go to "/robots.txt" Then I should see "Disallow: /" And I should not see "Allow:" + + @unauthenticated + Scenario: When I go to the home page, I can see Visualisations and News and Case Studies in the navbar + Given "Unauthenticated" as the persona + When I go to homepage + Then I should see an element with xpath "//a[string()='Visualisations']" + And I should see an element with xpath "//a[string()='News and Case Studies']" diff --git a/test/features/data_usability_rating.feature b/test/features/data_usability_rating.feature index 444e647..438ff13 100644 --- a/test/features/data_usability_rating.feature +++ b/test/features/data_usability_rating.feature @@ -1,5 +1,6 @@ @data_usability_rating @OpenData +@multi_plugin Feature: Data usability rating Scenario Outline: As a publisher, when I create a resource with an open license, I can verify the openness score is correct @@ -7,7 +8,7 @@ Feature: Data usability rating When I log in And I create a dataset and resource with key-value parameters "license=other-open" and "format=::upload=" And I press the element with xpath "//ol[contains(@class, 'breadcrumb')]//a[starts-with(@href, '/dataset/')]" - And I reload page every 3 seconds until I see an element with xpath "//div[contains(@class, 'qa') and contains(@class, 'openness-')]" but not more than 3 times + And I reload page every 3 seconds until I see an element with xpath "//div[contains(@class, 'qa') and contains(@class, 'openness-')]" but not more than 10 times Then I should see "Data usability rating" When I press "Test Resource" Then I should see an element with xpath "//div[contains(@class, 'qa openness-')]" @@ -20,3 +21,15 @@ Feature: Data usability rating | CSV | csv_resource.csv | 3 | | JSON | json_resource.json | 3 | | RDF | rdf_resource.rdf | 4 | + + Scenario: As a publisher, when I create an open resource with a matching schema, I can verify the score is upgraded from 3 to 4 + Given "TestOrgEditor" as the persona + When I log in + And I create a dataset and resource with key-value parameters "license=other-open" and "format=CSV::upload=test_game_data.csv::schema=default" + And I press the element with xpath "//ol[contains(@class, 'breadcrumb')]//a[starts-with(@href, '/dataset/')]" + And I reload page every 3 seconds until I see an element with xpath "//div[contains(@class, 'qa') and contains(@class, 'openness-4')]" but not more than 10 times + Then I should not see an element with xpath "//div[contains(@class, 'openness-3')]" + And I should see an element with xpath "//div[contains(@class, 'openness-4')]" + When I take a debugging screenshot + And I press "Test Resource" + Then I should see an element with xpath "//div[contains(@class, 'qa openness-4')]" diff --git a/test/features/data_validation.feature b/test/features/data_validation.feature index a70e897..f0ca0a9 100644 --- a/test/features/data_validation.feature +++ b/test/features/data_validation.feature @@ -1,5 +1,6 @@ @config @OpenData +@multi_plugin Feature: Data Validation Scenario Outline: As a sysadmin, admin and editor user of the dataset organisation I can see the 'JSON' button diff --git a/test/features/datarequest.feature b/test/features/datarequest.feature index 29ca2a7..5613f8f 100644 --- a/test/features/datarequest.feature +++ b/test/features/datarequest.feature @@ -1,5 +1,6 @@ @datarequest @OpenData +@multi_plugin Feature: Data Request @unauthenticated @@ -54,6 +55,16 @@ Feature: Data Request And I should see an element with the css selector "span.error-block" within 1 seconds And I should see "Description cannot be empty" within 1 seconds + Scenario: When a logged-in user submits a Data Request containing profanity they should receive an error message and the request will not be created + Given "TestOrgEditor" as the persona + When I log in + And I go to the data requests page + And I press "Add data request" + And I fill in title with random text + And I fill in "description" with "He had sheep, and oxen, and he asses, and menservants, and maidservants, and she asses, and camels." + And I press the element with xpath "//button[contains(@class, 'btn-primary') and contains(string(), 'Create data request')]" + Then I should see "Blocked due to profanity" within 5 seconds + Scenario: Data request creator and Sysadmin can see a 'Close' button on the data request detail page for opened data requests Given "SysAdmin" as the persona When I log in @@ -92,6 +103,51 @@ Feature: Data Request Then I should see an element with xpath "//i[contains(@class, 'icon-lock')]" And I should not see an element with xpath "//a[contains(string(), 'Close')]" + Scenario: Delete all data requests for a user + # Use a different profile so we don't delete any other test requests + Given "TestOrgAdmin" as the persona + When I log in + And I create a datarequest + And I create a datarequest + And I create a datarequest + And I go to the "test_org_admin" profile page + And I take a debugging screenshot + And I press the element with xpath "//ul[contains(@class, 'nav-tabs')]//a[contains(string(), 'Data Requests')]" + And I take a debugging screenshot + Then I should see an element with xpath "//a[@title='Delete' and contains(@class, 'btn-danger')]" + And I should not see an element with xpath "//a[contains(@class, 'btn-danger-serious')]" + + Given "SysAdmin" as the persona + When I log out + And I log in + And I go to the "test_org_admin" profile page + And I take a debugging screenshot + And I press the element with xpath "//ul[contains(@class, 'nav-tabs')]//a[contains(string(), 'Data Requests')]" + And I take a debugging screenshot + Then I should see an element with xpath "//a[@title='Delete' and contains(@class, 'btn-danger')]" + And I should see an element with xpath "//a[contains(@title, 'Delete all') and contains(@class, 'btn-danger-serious')]" + + When I press the element with xpath "//a[contains(@title, 'Delete all') and contains(@class, 'btn-danger-serious')][1]" + And I take a debugging screenshot + And I confirm the dialog containing "Are you sure you want to" if present + And I take a debugging screenshot + Then I should see an element with xpath "//div[contains(@class, 'alert') and contains(string(), 'Deleted') and contains(string(), 'data request(s)')]" + + When I go to the "test_org_admin" profile page + And I press the element with xpath "//ul[contains(@class, 'nav-tabs')]//a[contains(string(), 'Data Requests')]" + Then I should see "No data requests found" + + Scenario: An unprivileged user who tries to create multiple data requests close together should see an error + Given "CKANUser" as the persona + When I log in + And I create a datarequest + And I go to the data requests page + And I press "Add data request" + And I fill in title with random text + And I fill in "description" with "Test throttling" + And I press the element with xpath "//button[contains(@class, 'btn-primary')]" + Then I should see "Too many requests submitted, please wait" + Scenario: As an org admin I can re-open a closed data request Given "DataRequestOrgAdmin" as the persona When I log in diff --git a/test/features/datarequest_circumstances.feature b/test/features/datarequest_circumstances.feature index c2b5d59..67bb75c 100644 --- a/test/features/datarequest_circumstances.feature +++ b/test/features/datarequest_circumstances.feature @@ -1,5 +1,6 @@ @data-requests-circumstances @OpenData +@multi_plugin Feature: Datarequest-circumstances Scenario: As a sysadmin user when I go to the admin config page I can view the data requests closing circumstances textarea diff --git a/test/features/dataset_schema.feature b/test/features/dataset_schema.feature index 1315fcc..60e4eaf 100644 --- a/test/features/dataset_schema.feature +++ b/test/features/dataset_schema.feature @@ -1,5 +1,6 @@ @dataset_schema @OpenData +@multi_plugin Feature: Dataset Schema Scenario Outline: Add new dataset metadata fields for default data schema validation diff --git a/test/features/datasets.feature b/test/features/datasets.feature index 1e11592..1f9a727 100644 --- a/test/features/datasets.feature +++ b/test/features/datasets.feature @@ -1,3 +1,4 @@ +@dataset Feature: Dataset APIs Scenario: Creative Commons BY-NC-SA 4.0 licence is an option for datasets @@ -9,14 +10,12 @@ Feature: Dataset APIs Scenario: As a publisher, I can view the change history of a dataset Given "TestOrgEditor" as the persona When I log in - And I edit the "public-test-dataset" dataset - And I fill in "author_email" with "admin@example.com" - And I press the element with xpath "//form[@id='dataset-edit']//button[contains(@class, 'btn-primary')]" + And I create a dataset and resource with key-value parameters "notes=Testing activity stream" and "name=Test" And I press the element with xpath "//a[contains(@href, '/dataset/activity/') and contains(string(), 'Activity Stream')]" Then I should see "created the dataset" When I press "View this version" Then I should see "You're currently viewing an old version of this dataset." - When I go to dataset "public-test-dataset" + When I go to dataset "$last_generated_name" And I press the element with xpath "//a[contains(@href, '/dataset/activity/') and contains(string(), 'Activity Stream')]" And I press "Changes" Then I should see "View changes from" diff --git a/test/features/engagement_reporting.feature b/test/features/engagement_reporting.feature index 683e3d0..4144125 100644 --- a/test/features/engagement_reporting.feature +++ b/test/features/engagement_reporting.feature @@ -1,5 +1,6 @@ @reporting @OpenData +@multi_plugin Feature: Engagement Reporting Scenario Outline: As a user with admin or editor role capacity of an organisation, I can view 'My Reports' tab in the dashboard and show the engagement report with filters @@ -23,32 +24,19 @@ Feature: Engagement Reporting | TestOrgAdmin | | TestOrgEditor | - Scenario: As a data request organisation admin, when I view my engagement report, I can verify the number of data requests is correct and increments - Given "DataRequestOrgAdmin" as the persona - When I log in - And I go to my reports page - And I press "Engagement Report" - And I press the element with xpath "//button[contains(string(), 'Show')]" - Then I should see an element with xpath "//tr[@id='datarequests-total']/td[contains(@class, 'metric-title') and string()='Data requests' and position()=1]" - And I should see an element with xpath "//tr[@id='datarequests-total']/td[contains(@class, 'metric-data') and string()='30' and position()=2]" - - When I create a datarequest - And I go to my reports page - And I press "Engagement Report" - And I press the element with xpath "//button[contains(string(), 'Show')]" - Then I should see an element with xpath "//tr[@id='datarequests-total']/td[contains(@class, 'metric-title') and string()='Data requests' and position()=1]" - And I should see an element with xpath "//tr[@id='datarequests-total']/td[contains(@class, 'metric-data') and string()='31' and position()=2]" - Scenario: As an admin user of my organisation, when I view my engagement report, I can verify the numbers are correct and increment Given "ReportingOrgAdmin" as the persona When I log in And I go to my reports page And I press "Engagement Report" + And I take a debugging screenshot And I press the element with xpath "//button[contains(string(), 'Show')]" Then I should see an element with xpath "//tr[@id='dataset-followers']/td[contains(@class, 'metric-title') and string()='Dataset followers' and position()=1]" And I should see an element with xpath "//tr[@id='dataset-followers']/td[contains(@class, 'metric-data') and string()='0' and position()=2]" And I should see an element with xpath "//tr[@id='dataset-comments']/td[contains(@class, 'metric-title') and string()='Dataset comments' and position()=1]" And I should see an element with xpath "//tr[@id='dataset-comments']/td[contains(@class, 'metric-data') and string()='0' and position()=2]" + And I should see an element with xpath "//tr[@id='datarequests-total']/td[contains(@class, 'metric-title') and string()='Data requests' and position()=1]" + And I should see an element with xpath "//tr[@id='datarequests-total']/td[contains(@class, 'metric-data') and string()='1' and position()=2]" And I should see an element with xpath "//tr[@id='datarequest-comments']/td[contains(@class, 'metric-title') and string()='Data request comments' and position()=1]" And I should see an element with xpath "//tr[@id='datarequest-comments']/td[contains(@class, 'metric-data') and string()='0' and position()=2]" And I should see an element with xpath "//tr[contains(@class, 'closing-circumstance')]/td[position()=1]/a[contains(@href, '/closed?') and contains(string(), 'To be released as open data at a later date')]" @@ -62,6 +50,7 @@ Feature: Engagement Reporting And I submit a comment with subject "Test subject" and comment "This is a test comment" And I go to data request "Reporting Request" comments And I submit a comment with subject "Test subject" and comment "This is a test comment" + And I create a data request in the "Reporting Organisation" organisation And I go to data request "Reporting Request" And I press the element with xpath "//a[contains(string(), 'Close')]" And I select "To be released as open data at a later date" from "close_circumstance" @@ -75,6 +64,8 @@ Feature: Engagement Reporting And I should see an element with xpath "//tr[@id='dataset-followers']/td[contains(@class, 'metric-data') and string()='1' and position()=2]" And I should see an element with xpath "//tr[@id='dataset-comments']/td[contains(@class, 'metric-title') and string()='Dataset comments' and position()=1]" And I should see an element with xpath "//tr[@id='dataset-comments']/td[contains(@class, 'metric-data') and string()='1' and position()=2]" + And I should see an element with xpath "//tr[@id='datarequests-total']/td[contains(@class, 'metric-title') and string()='Data requests' and position()=1]" + And I should see an element with xpath "//tr[@id='datarequests-total']/td[contains(@class, 'metric-data') and string()='2' and position()=2]" And I should see an element with xpath "//tr[@id='datarequest-comments']/td[contains(@class, 'metric-title') and string()='Data request comments' and position()=1]" And I should see an element with xpath "//tr[@id='datarequest-comments']/td[contains(@class, 'metric-data') and string()='1' and position()=2]" And I should see an element with xpath "//tr[contains(@class, 'closing-circumstance')]/td[position()=1]/a[contains(@href, '/closed?') and contains(string(), 'To be released as open data at a later date')]" diff --git a/test/features/environment.py b/test/features/environment.py index 63c305d..a47f08f 100644 --- a/test/features/environment.py +++ b/test/features/environment.py @@ -118,4 +118,5 @@ def before_scenario(context, scenario): def after_scenario(context, scenario): + os.system("ckan_cli jobs clear") benv.after_scenario(context, scenario) diff --git a/test/features/groups.feature b/test/features/groups.feature index b607060..5ecce5e 100644 --- a/test/features/groups.feature +++ b/test/features/groups.feature @@ -1,4 +1,4 @@ -@users +@groups Feature: Group APIs Scenario Outline: Group membership is accessible to admins of the group @@ -39,3 +39,32 @@ Feature: Group APIs When I view the "silly-walks" group API "not including" users Then I should see an element with xpath "//*[contains(string(), '"success": true') and contains(string(), '"name": "silly-walks"')]" + + Scenario: As a sysadmin, when I create a group with a long name, it should be preserved + Given "SysAdmin" as the persona + When I log in + And I go to group page + And I click the link to "/group/new" + And I fill in title with random text starting with "Group name more than 35 characters" + And I set "group_title" to "$last_generated_title" + And I press the element with xpath "//button[contains(@class, 'btn-primary')]" + And I take a debugging screenshot + # Breadcrumb should be truncated but preserve full name in a tooltip + Then I should see an element with xpath "//ol[contains(@class, 'breadcrumb')]//a[contains(string(), 'Group name more') and contains(string(), '...') and @title = '$group_title']" + + # Search facets should be truncated but preserve full name in a tooltip + When I create a dataset and resource with key-value parameters "notes=Testing long group name" and "name=Test" + And I press "Groups" + When I select by text " $group_title" from "group_added" + And I press the element with xpath "//button[contains(@class, 'btn-primary')]" + Then I should see an element with xpath "//form//a[normalize-space() = '$group_title']" + When I press "$group_title" + + Then I should see an element with xpath "//li[contains(@class, 'nav-item')]//a[contains(string(), 'Group name more') and contains(string(), '...') and @title = '$group_title']" + When I press the element with xpath "//li[contains(@class, 'nav-item')]//a[contains(string(), 'Group name more') and contains(string(), '...') and @title = '$group_title']" + Then I should see an element with xpath "//li[contains(@class, 'nav-item') and contains(@class, 'active')]//a[contains(string(), 'Group name more') and contains(string(), '...') and @title = '$group_title']" + + When I go to dataset page + Then I should see an element with xpath "//li[contains(@class, 'nav-item')]//a[contains(string(), 'Group name more') and contains(string(), '...') and @title = '$group_title']" + When I press the element with xpath "//li[contains(@class, 'nav-item')]//a[contains(string(), 'Group name more') and contains(string(), '...') and @title = '$group_title']" + Then I should see an element with xpath "//li[contains(@class, 'nav-item') and contains(@class, 'active')]//a[contains(string(), 'Group name more') and contains(string(), '...') and @title = '$group_title']" diff --git a/test/features/organisations.feature b/test/features/organisations.feature index 854efe3..eac7063 100644 --- a/test/features/organisations.feature +++ b/test/features/organisations.feature @@ -1,4 +1,4 @@ -@users +@organisations Feature: Organization APIs Scenario Outline: Organisation membership is accessible to admins of the organisation @@ -40,3 +40,33 @@ Feature: Organization APIs When I view the "test-organisation" organisation API "not including" users Then I should see an element with xpath "//*[contains(string(), '"success": true') and contains(string(), '"name": "test-organisation"')]" + + Scenario: Organisation list is accessible via the dashboard + Given "SysAdmin" as the persona + When I log in + And I go to the dashboard + And I press "My Organisations" + Then I should see "Test Organisation" + And I should see an element with xpath "//a[contains(@href, 'organization/new') and contains(string(), 'Add Organisation')]" + + Scenario: As a sysadmin, when I create an organisation with a long name, it should be preserved + Given "SysAdmin" as the persona + When I log in + And I go to organisation page + And I click the link to "/organization/new" + And I fill in title with random text starting with "Org name more than 35 characters" + And I press the element with xpath "//button[contains(@class, 'btn-primary')]" + And I take a debugging screenshot + # Breadcrumb should be truncated but preserve full name in a tooltip + Then I should see an element with xpath "//ol[contains(@class, 'breadcrumb')]//a[contains(string(), 'Org name more than') and contains(string(), '...') and contains(@title, 'Org name more than 35 characters')]" + + # Search facets should be truncated but preserve full name in a tooltip + When I create a dataset and resource with key-value parameters "notes=Testing long org name::owner_org=Org name more than" and "name=Test" + And I press "Org name more than" + Then I should see an element with xpath "//li[contains(@class, 'nav-item')]//a[contains(string(), 'Org name more than') and contains(string(), '...') and contains(@title, 'Org name more than 35 characters')]" + When I press the element with xpath "//li[contains(@class, 'nav-item')]//a[contains(string(), 'Org name more than') and contains(string(), '...') and contains(@title, 'Org name more than 35 characters')]" + Then I should see an element with xpath "//li[contains(@class, 'nav-item') and contains(@class, 'active')]//a[contains(string(), 'Org name more than') and contains(string(), '...') and contains(@title, 'Org name more than 35 characters')]" + When I go to dataset page + Then I should see an element with xpath "//li[contains(@class, 'nav-item')]//a[contains(string(), 'Org name more than') and contains(string(), '...') and contains(@title, 'Org name more than 35 characters')]" + When I press the element with xpath "//li[contains(@class, 'nav-item')]//a[contains(string(), 'Org name more than') and contains(string(), '...') and contains(@title, 'Org name more than 35 characters')]" + Then I should see an element with xpath "//li[contains(@class, 'nav-item') and contains(@class, 'active')]//a[contains(string(), 'Org name more than') and contains(string(), '...') and contains(@title, 'Org name more than 35 characters')]" diff --git a/test/features/reporting.feature b/test/features/reporting.feature index 436a16b..d18a62d 100644 --- a/test/features/reporting.feature +++ b/test/features/reporting.feature @@ -1,5 +1,6 @@ @reporting @OpenData +@multi_plugin Feature: Reporting @unauthenticated @@ -12,12 +13,40 @@ Feature: Reporting And I should see an element with xpath "//table[@id='report-table']//th[contains(string(), 'Broken links')]" And I should see an element with xpath "//table[@id='report-table']//td[position()=1]/a[contains(@href, 'report/broken-links') and contains(string(), 'Test Organisation')]" + When I press "Test Organisation" + Then I should see an element with xpath "//table[@id='report-table']//th[string() = 'Res']" + And I should see an element with xpath "//table[@id='report-table']//th[string() = 'URL']" + And I should see an element with xpath "//table[@id='report-table']//th[string() = 'Status']" + And I should see an element with xpath "//table[@id='report-table']//th[string() = 'Reason']" + + When I go back + Then I should see an element with xpath "//select[@name='organization']" + When I select "test-organisation" from "organization" + Then I should see an element with xpath "//table[@id='report-table']//th[string() = 'Res']" + And I should see an element with xpath "//table[@id='report-table']//th[string() = 'URL']" + And I should see an element with xpath "//table[@id='report-table']//th[string() = 'Status']" + And I should see an element with xpath "//table[@id='report-table']//th[string() = 'Reason']" + @unauthenticated Scenario: I can view a 'Data Usability Rating' report anonymously Given "Unauthenticated" as the persona When I visit "/report" And I press "Data usability rating" Then I should see an element with xpath "//select[@name='organization']" - And I should see an element with xpath "//table[@id='report-table']//th[contains(string(), 'Score TBC')]" - And I should see an element with xpath "//table[@id='report-table']//th[contains(string(), 'Average score')]" + And I should see an element with xpath "//table[@id='report-table']//th[string() = 'Score TBC']" + And I should see an element with xpath "//table[@id='report-table']//th[string() = 'Average score']" And I should see an element with xpath "//table[@id='report-table']//td[position()=1]/a[contains(@href, 'report/openness') and contains(string(), 'Test Organisation')]" + + When I press "Test Organisation" + Then I should see an element with xpath "//table[@id='report-table']//th[string() = 'Dataset']" + And I should see an element with xpath "//table[@id='report-table']//th[string() = 'Notes']" + And I should see an element with xpath "//table[@id='report-table']//th[string() = 'Score']" + And I should see an element with xpath "//table[@id='report-table']//th[string() = 'Reason']" + + When I go back + Then I should see an element with xpath "//select[@name='organization']" + When I select "test-organisation" from "organization" + Then I should see an element with xpath "//table[@id='report-table']//th[string() = 'Dataset']" + And I should see an element with xpath "//table[@id='report-table']//th[string() = 'Notes']" + And I should see an element with xpath "//table[@id='report-table']//th[string() = 'Score']" + And I should see an element with xpath "//table[@id='report-table']//th[string() = 'Reason']" diff --git a/test/features/resource_freshness.feature b/test/features/resource_freshness.feature index 5371946..5578505 100644 --- a/test/features/resource_freshness.feature +++ b/test/features/resource_freshness.feature @@ -14,18 +14,18 @@ Feature: Resource freshness | TestOrgAdmin | | TestOrgEditor | - Scenario Outline: An editor, admin or sysadmin user, when I go to the dataset new page and select 'monthly' update frequency, then the text 'Next update due' should be visible + Scenario Outline: An editor, admin or sysadmin user, when I go to the dataset new page and select an update frequency, then the text 'Next update due' should be visible Given "" as the persona When I log in And I go to "/dataset/new" - And I select "monthly" from "update_frequency" + And I select "" from "update_frequency" Then I should see "Next update due" - Examples: Users - | User | - | SysAdmin | - | TestOrgAdmin | - | TestOrgEditor | + Examples: Frequencies + | User | Frequency | + | SysAdmin | monthly | + | TestOrgAdmin | biennially | + | TestOrgEditor | quadrennially | Scenario Outline: As a user with editing privileges, when I set a 'monthly' update frequently, I should still be able to update the dataset via the API Given "" as the persona diff --git a/test/features/schema_generation.feature b/test/features/schema_generation.feature index 1c5a8a8..bcd130b 100644 --- a/test/features/schema_generation.feature +++ b/test/features/schema_generation.feature @@ -1,4 +1,5 @@ @OpenData +@multi_plugin Feature: Schema Generation Enable worker with `ckan jobs clear && ckan jobs worker`, since these tests rely on background tasks diff --git a/test/features/steps/steps.py b/test/features/steps/steps.py index 170b0c7..7adb265 100644 --- a/test/features/steps/steps.py +++ b/test/features/steps/steps.py @@ -24,6 +24,7 @@ URL_RE = re.compile(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|\ (?:%[0-9a-fA-F][0-9a-fA-F]))+', re.I | re.S | re.U) +SINGLE_QUOTE_RE = re.compile(r"(^|[^\\])'") dataset_default_schema = """ {"fields": [ @@ -96,7 +97,7 @@ def log_in_directly(context): assert context.persona, "A persona is required to log in, found [{}] in context. Have you configured the personas in before_scenario?".format(context.persona) context.execute_steps(u""" When I attempt to log in with password "$password" - Then I should see an element with xpath "//a[@title='Log out']" + Then I should see an element with xpath "//*[@title='Log out']/i[contains(@class, 'fa-sign-out')]" """) @@ -130,7 +131,7 @@ def request_reset(context): @when(u'I fill in "{name}" with "{value}" if present') def fill_in_field_if_present(context, name, value): context.execute_steps(u""" - When I execute the script "field = $('#field-{0}'); if (!field.length) field = $('#{0}'); if (!field.length) field = $('[name={0}]'); field.val('{1}'); field.keyup();" + When I execute the script "field = $('#{0}'); if (!field.length) field = $('[name={0}]'); if (!field.length) field = $('#field-{0}'); field.val('{1}'); field.keyup();" """.format(name, value)) @@ -152,7 +153,8 @@ def confirm_dialog_if_present(context, text): return button_xpath = parent_xpath + "//button[contains(@class, 'btn-primary')]" context.execute_steps(u""" - When I press the element with xpath "{0}" + When I take a debugging screenshot + And I press the element with xpath "{0}" """.format(button_xpath)) @@ -193,13 +195,24 @@ def go_to_new_resource_form(context, name): @when(u'I fill in title with random text') def title_random_text(context): - assert context.persona context.execute_steps(u""" - When I fill in "title" with "Test Title {0}" - And I fill in "name" with "test-title-{0}" if present - And I set "last_generated_title" to "Test Title {0}" - And I set "last_generated_name" to "test-title-{0}" - """.format(uuid.uuid4())) + When I fill in title with random text starting with "Test Title " + """) + + +@when(u'I fill in title with random text starting with "{prefix}"') +def title_random_text_with_prefix(context, prefix): + random_text = str(uuid.uuid4()) + title = prefix + random_text + name = prefix.lower().replace(" ", "-") + random_text + assert context.persona + context.execute_steps(f""" + When I fill in "title" with "{title}" + And I fill in "name" with "{name}" if present + And I set "last_generated_title" to "{title}" + And I set "last_generated_name" to "{name}" + And I take a debugging screenshot + """) @when(u'I go to dataset page') @@ -250,6 +263,15 @@ def select_licence(context, licence_id): """.format(licence_id)) +@when(u'I select the organisation with title "{title}"') +def select_organisation(context, title): + # Organisation requires special interaction due to fancy JavaScript + context.execute_steps(u""" + When I execute the script "org_uuid=$('#field-organizations').find('option:contains({0})').val(); $('#field-organizations').val(org_uuid).trigger('change')" + And I take a debugging screenshot + """.format(title)) + + @when(u'I enter the resource URL "{url}"') def enter_resource_url(context, url): if url != "default": @@ -292,7 +314,7 @@ def fill_in_default_link_resource_fields(context): @when(u'I upload "{file_name}" of type "{file_format}" to resource') def upload_file_to_resource(context, file_name, file_format): context.execute_steps(u""" - When I execute the script "$('#resource-upload-button').trigger(click);" + When I execute the script "$('#resource-upload-button').trigger('click');" And I attach the file "{file_name}" to "upload" # Don't quote the injected string since it can have trailing spaces And I execute the script "document.getElementById('field-format').value='{file_format}'" @@ -300,6 +322,14 @@ def upload_file_to_resource(context, file_name, file_format): """.format(file_name=file_name, file_format=file_format)) +@when(u'I upload schema file "{file_name}" to resource') +def upload_schema_file_to_resource(context, file_name): + context.execute_steps(u""" + When I execute the script "$('#field-schema-json ~ a.btn-remove-url').trigger('click');" + And I attach the file "{file_name}" to "schema_upload" + """.format(file_name=file_name)) + + @when(u'I go to group page') def go_to_group_page(context): context.execute_steps(u""" @@ -431,8 +461,8 @@ def _create_dataset_from_params(context, params): if key == "owner_org": # Owner org uses UUIDs as its values, so we need to rely on displayed text context.execute_steps(u""" - When I select by text "{1}" from "{0}" - """.format(key, value)) + When I select the organisation with title "{0}" + """.format(value)) elif key in ["update_frequency", "request_privacy_assessment", "private"]: context.execute_steps(u""" When I select "{1}" from "{0}" @@ -525,6 +555,12 @@ def create_resource_from_params(context, resource_params): if value == "default": value = resource_default_schema _enter_manual_schema(context, value) + elif key == "schema_upload": + if value == "default": + value = "test-resource_schemea.json" + context.execute_steps(u""" + When I upload schema file "{0}" to resource + """.format(value)) else: context.execute_steps(u""" When I fill in "{0}" with "{1}" if present @@ -573,7 +609,7 @@ def go_to_admin_config(context): @when(u'I log out') def log_out(context): context.execute_steps(u""" - When I visit "/user/_logout" + When I press the element with xpath "//*[@title='Log out']" Then I should see "Log in" """) @@ -658,6 +694,13 @@ def comment_form_not_visible(context): """) +def escape_for_javascript_string(text): + """ Escape a text so that it's suitable to be injected into a + single-quoted JavaScript string. + """ + return SINGLE_QUOTE_RE.sub(r"\1\\'", text) + + @when(u'I submit a comment with subject "{subject}" and comment "{comment}"') def submit_comment_with_subject_and_comment(context, subject, comment): """ @@ -670,10 +713,10 @@ def submit_comment_with_subject_and_comment(context, subject, comment): """ context.browser.execute_script(""" document.querySelector('form#comment_form input[name="subject"]').value = '%s'; - """ % subject) + """ % escape_for_javascript_string(subject)) context.browser.execute_script(""" document.querySelector('form#comment_form textarea[name="comment"]').value = '%s'; - """ % comment) + """ % escape_for_javascript_string(comment)) context.browser.execute_script(""" document.querySelector('form#comment_form .form-actions input[type="submit"]').click(); """) @@ -739,15 +782,25 @@ def go_to_data_request(context, subject): @when(u'I create a datarequest') def create_datarequest(context): + assert context.persona + context.execute_steps(u""" + When I create a data request in the "Open Data Administration" organisation + """) + + +@when(u'I create a data request in the "{organisation_name}" organisation') +def create_datarequest_for_org(context, organisation_name): assert context.persona context.execute_steps(u""" When I go to the data requests page And I press "Add data request" And I fill in title with random text And I fill in "description" with "Test description" - And I execute the script "$('#field-organizations option:contains("Open Data Administration")').attr('selected', true)" + And I execute the script "$('#field-organizations option:contains("{0}")').attr('selected', true)" + And I take a debugging screenshot And I press the element with xpath "//button[contains(@class, 'btn-primary')]" - """) + And I take a debugging screenshot + """.format(organisation_name)) @when(u'I go to data request "{subject}" comments')