diff --git a/.github/workflows/formplayer.yml b/.github/workflows/formplayer.yml index 95e37fd75..dd79c6d62 100644 --- a/.github/workflows/formplayer.yml +++ b/.github/workflows/formplayer.yml @@ -8,8 +8,8 @@ on: branches: [ master ] pull_request: branches: [ master ] - repository_dispatch: - types: [ deploy_success ] + schedule: + - cron: '0 0 * * 0' workflow_dispatch: inputs: @@ -20,22 +20,18 @@ on: type: choice options: - staging - + - production concurrency: - group: tests-on-formplayer-${{ github.ref }} + group: lookup-table-tests-${{ github.ref }} cancel-in-progress: true jobs: set_matrix: runs-on: ubuntu-latest outputs: - matrix: ${{ steps.set-matrix-deploy.outputs.matrix || steps.set-matrix-manual.outputs.matrix || steps.set-matrix-default.outputs.matrix }} + matrix: ${{ steps.set-matrix-manual.outputs.matrix || steps.set-matrix-default.outputs.matrix }} steps: - - id: set-matrix-deploy - if: ${{ github.event_name == 'repository_dispatch' }} - run: | - echo "::set-output name=matrix::{\"environment\": [\"${{ github.event.client_payload.environment }}\"]}" - id: set-matrix-manual if: ${{ github.event_name == 'workflow_dispatch' }} run: | @@ -43,14 +39,13 @@ jobs: - id: set-matrix-default if: ${{ !contains(github.event_name , 'dispatch') }} run: | - echo "::set-output name=matrix::{\"environment\": [\"staging\"]}" - + echo "::set-output name=matrix::{\"environment\": [\"production\", \"staging\"]}" build: needs: set_matrix strategy: fail-fast: false matrix: ${{ fromJSON(needs.set_matrix.outputs.matrix) }} - name: Formplayer on '${{ matrix.environment }}' + name: Lookup tests on '${{ matrix.environment }}' runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 @@ -63,24 +58,21 @@ jobs: run: | python -m pip install --upgrade pip pip install -r Formplayer/requires.txt - - - name: Formplayer Test with pytest + - name: Lookup table tests with pytest env: - DIMAGIQA_ENV: ${{ matrix.environment }} #${{ secrets.DIMAGIQA_URL }} + DIMAGIQA_ENV: ${{ matrix.environment }} DIMAGIQA_LOGIN_USERNAME: ${{ secrets.DIMAGIQA_LOGIN_USERNAME }} DIMAGIQA_LOGIN_PASSWORD: ${{ secrets.DIMAGIQA_LOGIN_PASSWORD }} DIMAGIQA_MAIL_USERNAME: ${{ secrets.DIMAGIQA_MAIL_USERNAME }} DIMAGIQA_MAIL_PASSWORD: ${{ secrets.DIMAGIQA_MAIL_PASSWORD }} DIMAGIQA_STAGING_AUTH_KEY: ${{ secrets.DIMAGIQA_STAGING_AUTH_KEY }} DIMAGIQA_PROD_AUTH_KEY: ${{ secrets.DIMAGIQA_PROD_AUTH_KEY }} - run: | echo "client_payload: ${{ toJson(github.event.client_payload) }}" echo "matrix environment: ${{ matrix.environment }}" echo "NOW=$(date +'%m-%d %H:%M')" >> $GITHUB_ENV echo ${{env.NOW}} - pytest -v --rootdir= Formplayer/testCases -n auto --dist=loadfile --html=report_${{ matrix.environment }}.html - + pytest -v --rootdir= Formplayer/testCases -n 3 --dist=loadfile --reruns 1 --html=formplayer_${{ matrix.environment }}.html - name: Set email vars if: ${{ success() || failure() }} id: configure_email @@ -91,39 +83,34 @@ jobs: with: script: | const { promises: fs } = require('fs') - const {JOB_STATUS, NOW, CC_ENV, GITHUB_HEAD_REF} = process.env - const prefix = `[${CC_ENV}] Formplayer Tests - ${JOB_STATUS.toUpperCase()} - Run #${context.runNumber}` + const prefix = `[${CC_ENV}] Lookuptable Tests - ${JOB_STATUS.toUpperCase()} - Run #${context.runNumber}` const suffix = `at ${NOW}` + let subject = `${prefix} on branch "${GITHUB_HEAD_REF}" ${suffix}` - let subject = `${prefix} on "deploy_success" ${suffix}` - if (context.eventName !== "repository_dispatch") { - subject = `${prefix} on branch "${GITHUB_HEAD_REF}" ${suffix}` - } - - let bodyFile = './Formplayer/email_pass.md' + let bodyFile = './common_utilities/mail_templates/email_pass.md' if (JOB_STATUS !== 'success') { - bodyFile = './Formplayer/email_fail.md' + bodyFile = './common_utilities/mail_templates/email_fail.md' } - + let actionRunLink = context.payload.repository.html_url + `/actions/runs/${context.runId}` + let testSuite = 'Formplayer Regression' let bodyContent = await fs.readFile(bodyFile, 'utf8') bodyContent = bodyContent.replace(/{{actionRunLink}}/g, actionRunLink) .replace(/{{runNumber}}/g, context.runNumber) .replace(/{{environment}}/g, CC_ENV) - + .replace(/{{testSuite}}/g, testSuite) + let receivers = 'qa-automation@dimagi.com' if (context.eventName !== "pull_request" || context.eventName !== "push") { - receivers = 'qa@dimagi.com, sameena.shaik@fissionlabs.com' + receivers = 'kbordoloi@dimagi.com' } - return { "subject": subject, "body": bodyContent, "reference": Math.random().toString(36).substr(2), // used to prevent threading of similar emails "receivers": receivers } - - name: Send Result Email if: ${{ success() || failure() }} uses: dawidd6/action-send-mail@v3 @@ -137,13 +124,126 @@ jobs: from: <${{secrets.DIMAGIQA_MAIL_USERNAME}}> html_body: ${{ fromJSON(steps.configure_email.outputs.result).body }} convert_markdown: true - attachments: ${{ github.workspace }}/report_${{ matrix.environment }}.html + attachments: ${{ github.workspace }}/formplayer_${{ matrix.environment }}.html in_reply_to: ${{ fromJSON(steps.configure_email.outputs.result).reference }} + - name: Post to Slack channel on Failure + id: slack_fail + uses: slackapi/slack-github-action@v1.23.0 + if: failure() + with: + payload: | + { + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": " Hey Folks!! :bye_boo: \n*${{ github.workflow }}* were just triggered!" + } + }, + { + "type": "context", + "elements": [ + { + "type": "mrkdwn", + "text": "*Environment: *\n ${{ matrix.environment }} \n" + }, + { + "type": "mrkdwn", + "text": " " + }, + { + "type": "mrkdwn", + "text": "*Status: *\n ${{ job.status }} :x:" + } + ] + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Here's the corresponding workflow execution :arrow_right::arrow_right:" + }, + "accessory": { + "type": "button", + "text": { + "type": "plain_text", + "text": "View on Github", + "emoji": true + }, + "value": "click_me_123", + "url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "action_id": "button-action", + "style": "danger" + } + } + ] + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL_FEATURES }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK + + - name: Post to Slack channel on Success + id: slack_pass + uses: slackapi/slack-github-action@v1.23.0 + if: success() + with: + payload: | + { + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": " Hey Folks!! :bye_boo: \n*${{ github.workflow }}* were just triggered!" + } + }, + { + "type": "context", + "elements": [ + { + "type": "mrkdwn", + "text": "*Environment: *\n ${{ matrix.environment }} \n" + }, + { + "type": "mrkdwn", + "text": " " + }, + { + "type": "mrkdwn", + "text": "*Status: *\n ${{ job.status }} :white_check_mark:" + } + ] + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Here's the corresponding workflow execution :arrow_right::arrow_right:" + }, + "accessory": { + "type": "button", + "text": { + "type": "plain_text", + "text": "View on Github", + "emoji": true + }, + "value": "click_me_123", + "url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "action_id": "button-action", + "style": "primary" + } + } + ] + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL_FEATURES }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK + - name: Archive test results if: ${{ success() || failure() }} uses: actions/upload-artifact@v2 with: name: test-result-reports-${{ matrix.environment }} - path: ${{ github.workspace }}/report_${{ matrix.environment }}.html - retention-days: 2 \ No newline at end of file + path: ${{ github.workspace }}/formplayer_${{ matrix.environment }}.html \ No newline at end of file diff --git a/Formplayer/testCases/test_04_basic_test_forms.py b/Formplayer/testCases/test_04_basic_test_forms.py index e2d4237c0..1c1f88173 100644 --- a/Formplayer/testCases/test_04_basic_test_forms.py +++ b/Formplayer/testCases/test_04_basic_test_forms.py @@ -7,6 +7,7 @@ from Formplayer.testPages.webapps.login_as_page import LoginAsPage from Formplayer.userInputs.user_inputs import UserData + def test_case_16_incomplete_form_app_preview(driver, settings): app_preview = LoginAsAppPreviewPage(driver, settings) basic = BasicTestAppPreview(driver) @@ -28,6 +29,7 @@ def test_case_16_incomplete_form_app_preview(driver, settings): basic.verify_saved_form_and_submit_changed(basic.name_input1) basic.verify_submit_history(basic.changed_name_input, UserData.app_preview_mobile_worker) + def test_case_17_incomplete_form_web_apps(driver, settings): login = LoginAsPage(driver, settings) login.open_webapps_menu() @@ -51,6 +53,7 @@ def test_case_17_incomplete_form_web_apps(driver, settings): basic.verify_saved_form_and_submit_changed(basic.name_input1) basic.verify_submit_history(basic.changed_name_input, UserData.app_preview_mobile_worker) + def test_case_18_data_preview_app_preview(driver, settings): app_preview = LoginAsAppPreviewPage(driver, settings) basic = BasicTestAppPreview(driver) @@ -59,6 +62,7 @@ def test_case_18_data_preview_app_preview(driver, settings): expression = basic.random_expression() basic.verify_data_preview(expression) + def test_case_18_data_preview_web_apps(driver, settings): login = LoginAsPage(driver, settings) login.open_webapps_menu() @@ -69,6 +73,7 @@ def test_case_18_data_preview_web_apps(driver, settings): expression = app_preview.random_expression() basic.verify_data_preview(expression) + def test_case_19_group_app_preview(driver, settings): app_preview = LoginAsAppPreviewPage(driver, settings) basic = BasicTestAppPreview(driver) @@ -77,6 +82,7 @@ def test_case_19_group_app_preview(driver, settings): basic.open_form(UserData.basic_tests_app['case_list'], UserData.basic_test_app_forms['group']) basic.group() + def test_case_19_group_web_apps(driver, settings): login = LoginAsPage(driver, settings) login.open_webapps_menu() @@ -96,6 +102,7 @@ def test_case_20_end_of_navigation_app_preview(driver, settings): basic.open_form(UserData.basic_test_app_forms['eofn'], UserData.basic_test_app_forms['home']) basic.end_of_navigation_module(UserData.basic_test_app_forms['eofn']) + def test_case_20_end_of_navigation_web_apps(driver, settings): login = LoginAsPage(driver, settings) login.open_webapps_menu() @@ -105,6 +112,7 @@ def test_case_20_end_of_navigation_web_apps(driver, settings): basic.open_form(UserData.basic_test_app_forms['eofn'], UserData.basic_test_app_forms['home']) basic.end_of_navigation_module(UserData.basic_test_app_forms['eofn'], settings) + def test_case_21_case_register_app_preview(driver, settings): app_preview = LoginAsAppPreviewPage(driver, settings) basic = BasicTestAppPreview(driver) @@ -156,6 +164,7 @@ def test_case_21_case_register_web_app(driver, settings): basic.open_form(UserData.basic_test_app_forms['case_test'], UserData.basic_test_app_forms['close_case']) basic.close_case(settings) + def test_case_22_unicode_verification_app_preview(driver, settings): app_preview = LoginAsAppPreviewPage(driver, settings) basic = BasicTestAppPreview(driver) @@ -167,6 +176,7 @@ def test_case_22_unicode_verification_app_preview(driver, settings): basic.open_form(UserData.basic_test_app_forms['case_test'], UserData.basic_test_app_forms['caselist']) basic.verify_updated_unicode() + def test_case_22_unicode_verification_web_app(driver, settings): login = LoginAsPage(driver, settings) login.open_webapps_menu() @@ -181,6 +191,7 @@ def test_case_22_unicode_verification_web_app(driver, settings): basic.open_form(UserData.basic_test_app_forms['case_test'], UserData.basic_test_app_forms['caselist']) basic.verify_updated_unicode() + def test_case_23_fixtures_app_preview(driver, settings): app_preview = LoginAsAppPreviewPage(driver, settings) basic = BasicTestAppPreview(driver) @@ -199,6 +210,7 @@ def test_case_23_fixtures_web_app(driver, settings): basic.open_form(UserData.basic_tests_app['case_list'], UserData.basic_test_app_forms['fixtures']) basic.fixtures_form() + def test_case_24_constraints_app_preview(driver, settings): app_preview = LoginAsAppPreviewPage(driver, settings) basic = BasicTestAppPreview(driver) @@ -207,6 +219,7 @@ def test_case_24_constraints_app_preview(driver, settings): basic.open_form(UserData.basic_test_app_forms['logic_test1'], UserData.basic_test_app_forms['constraints']) basic.constraint_form() + def test_case_24_constraints_web_apps(driver, settings): login = LoginAsPage(driver, settings) login.open_webapps_menu() @@ -216,6 +229,7 @@ def test_case_24_constraints_web_apps(driver, settings): basic.open_form(UserData.basic_test_app_forms['logic_test1'], UserData.basic_test_app_forms['constraints']) basic.constraint_form() + def test_case_25_functions_app_preview(driver, settings): app_preview = LoginAsAppPreviewPage(driver, settings) basic = BasicTestAppPreview(driver) @@ -224,6 +238,7 @@ def test_case_25_functions_app_preview(driver, settings): basic.open_form(UserData.basic_test_app_forms['logic_test1'], UserData.basic_test_app_forms['functions']) basic.functions_form() + def test_case_25_functions_web_apps(driver, settings): login = LoginAsPage(driver, settings) login.open_webapps_menu() @@ -233,6 +248,7 @@ def test_case_25_functions_web_apps(driver, settings): basic.open_form(UserData.basic_test_app_forms['logic_test1'], UserData.basic_test_app_forms['functions']) basic.functions_form() + def test_case_26_questions_app_preview(driver, settings): app_preview = LoginAsAppPreviewPage(driver, settings) basic = BasicTestAppPreview(driver) @@ -241,6 +257,7 @@ def test_case_26_questions_app_preview(driver, settings): basic.open_form(UserData.basic_tests_app['case_list'], UserData.basic_test_app_forms['question']) basic.questions_form() + def test_case_26_questions_web_apps(driver, settings): login = LoginAsPage(driver, settings) login.open_webapps_menu() @@ -250,8 +267,9 @@ def test_case_26_questions_web_apps(driver, settings): basic.open_form(UserData.basic_tests_app['case_list'], UserData.basic_test_app_forms['question']) basic.questions_form() -@pytest.mark.xfail("functionality not working via automation") + def test_case_27_webapps_forced_refresh(driver, settings): + pytest.xfail("functionality not working via automation") project = ProjectSettingsPage(driver, settings) project.clear_inactivity_timeout() login = LoginAsPage(driver, settings) @@ -279,12 +297,14 @@ def test_case_28_pagination_web_apps(driver, settings): basic = BasicTestWebApps(driver) basic.verify_pagination() + def test_case_28_pagination_app_preview(driver, settings): app_preview = LoginAsAppPreviewPage(driver, settings) basic = BasicTestAppPreview(driver) app_preview.open_view_app_preview(UserData.basic_tests_app['tests_app']) basic.verify_pagination() + def test_case_34_form_linking_app_preview(driver, settings): app_preview = LoginAsAppPreviewPage(driver, settings) basic = BasicTestAppPreview(driver) @@ -300,4 +320,4 @@ def test_case_34_form_linking_app_preview(driver, settings): basic.no_conditional_expression_form(case, cond) # app_preview.open_basic_tests_app(UserData.basic_tests_app['tests_app2']) basic.open_form(UserData.basic_test_app_forms['form_linking'], UserData.basic_test_app_forms['form_linking_child']) - basic.form_linking_child(case,child) + basic.form_linking_child(case, child) diff --git a/Formplayer/testPages/app_preview/login_as_app_preview_page.py b/Formplayer/testPages/app_preview/login_as_app_preview_page.py index 54c85c6dd..02d3ad967 100644 --- a/Formplayer/testPages/app_preview/login_as_app_preview_page.py +++ b/Formplayer/testPages/app_preview/login_as_app_preview_page.py @@ -92,8 +92,10 @@ def login_as_app_preview_content(self): def login_as_app_preview_form_submission(self, text): self.switch_to_frame(self.iframe) self.wait_to_click(self.start_option) - self.wait_to_click(self.basic_tests_case) - self.wait_to_click(self.basic_tests_form) + self.wait_for_element(self.basic_tests_case) + self.js_click(self.basic_tests_case) + self.wait_for_element(self.basic_tests_form) + self.js_click(self.basic_tests_form) self.wait_to_clear_and_send_keys(self.basic_tests_answer_input, text+Keys.TAB) self.js_click(self.next_button) time.sleep(2) diff --git a/Formplayer/testPages/basic_test_app/basic_test_web_apps.py b/Formplayer/testPages/basic_test_app/basic_test_web_apps.py index c0867204c..beaa2da10 100644 --- a/Formplayer/testPages/basic_test_app/basic_test_web_apps.py +++ b/Formplayer/testPages/basic_test_app/basic_test_web_apps.py @@ -395,11 +395,12 @@ def group(self): assert self.is_present((By.XPATH, self.county_options.format("Wilmington"))) assert self.is_present((By.XPATH, self.county_options.format("Cambridge"))) self.js_click((By.XPATH, self.county_options.format("Cambridge"))) + time.sleep(1) self.scroll_to_element((By.XPATH, self.choose_radio_button.format( - "Now we'll test other grouping structures. Do you want to skip the first group?", + "Do you want to skip the first group?", 'Yes'))) self.js_click((By.XPATH, self.choose_radio_button.format( - "Now we'll test other grouping structures. Do you want to skip the first group?", + "Do you want to skip the first group?", 'Yes'))) self.scroll_to_element((By.XPATH, self.choose_radio_button.format( "The next section tests groups within other groups. Which parts of the group do you want to skip?", diff --git a/Formplayer/testPages/messaging/messaging_page.py b/Formplayer/testPages/messaging/messaging_page.py index 261c1d725..677eb2026 100644 --- a/Formplayer/testPages/messaging/messaging_page.py +++ b/Formplayer/testPages/messaging/messaging_page.py @@ -22,7 +22,7 @@ def __init__(self, driver, settings): self.MESSAGING_TITLE = "Dashboard : Messaging :: - CommCare HQ" self.KEYWORDS_TITLE = "Keywords : Messaging :: - CommCare HQ" - self.keyword_delete_button = "//td[.//a[.='{}']]//following-sibling::td/a[contains(@data-bind,'delete')]" + self.keyword_delete_button = "//td[.//a[.='{}']]//following-sibling::td/button[contains(@data-bind,'delete')]" self.confirm_delete = "//td[.//a[.='{}']]//following-sibling::td//a[.='Cancel']//preceding-sibling::a[contains(@class,'confirm')]/i[@class='fa fa-remove']" self.add_keyword_button = (By.XPATH, "//a[contains(@href,'keywords/normal/add/')]")