diff --git a/.github/workflows/backend_tests.yml b/.github/workflows/backend_tests.yml index 365f8a44..deed1448 100644 --- a/.github/workflows/backend_tests.yml +++ b/.github/workflows/backend_tests.yml @@ -1,4 +1,4 @@ -name: Tests +name: Backend Tests on: - push @@ -283,7 +283,7 @@ jobs: # so just skip everything but main if: github.ref_name == 'main' with: - projectBaseDir: spiffworkflow-backend + projectBaseDir: spiffworkflow-frontend env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.github/workflows/frontend_tests.yml b/.github/workflows/frontend_tests.yml new file mode 100644 index 00000000..f1774965 --- /dev/null +++ b/.github/workflows/frontend_tests.yml @@ -0,0 +1,127 @@ +name: Frontend Tests + +on: + - push + - pull_request + +defaults: + run: + working-directory: spiffworkflow-backend + +# https://docs.github.com/en/actions/using-workflows/reusing-workflows + +jobs: + tests: + runs-on: ubuntu-latest + steps: + - name: Development Code + uses: actions/checkout@v3 + with: + # Disabling shallow clone is recommended for improving relevancy of reporting in sonarcloud + fetch-depth: 0 + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: 18.x + - run: npm install + - run: npm run lint + - run: npm test + - run: npm run build --if-present + - name: SonarCloud Scan + # thought about just skipping dependabot + # if: ${{ github.actor != 'dependabot[bot]' }} + # but figured all pull requests seems better, since none of them will have access to sonarcloud. + # however, with just skipping pull requests, the build associated with "Triggered via push" is also associated with the pull request and also fails hitting sonarcloud + # if: ${{ github.event_name != 'pull_request' }} + # so just skip everything but main + if: github.ref_name == 'main' + uses: sonarsource/sonarcloud-github-action@master + with: + projectBaseDir: spiffworkflow-frontend + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + # part about saving PR number and then using it from auto-merge-dependabot-prs from: + # https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run + - name: Save PR number + if: ${{ github.event_name == 'pull_request' }} + env: + PR_NUMBER: ${{ github.event.number }} + run: | + mkdir -p ./pr + echo "$PR_NUMBER" > ./pr/pr_number + - uses: actions/upload-artifact@v3 + with: + name: pr_number + path: pr/ + + cypress-run: + runs-on: ubuntu-20.04 + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Checkout Samples + uses: actions/checkout@v3 + with: + repository: sartography/sample-process-models + path: sample-process-models + - name: start_keycloak + working-directory: ./spiffworkflow-backend + run: ./bin/start_keycloak + - name: start_backend + working-directory: ./spiffworkflow-backend + run: ./bin/build_and_run_with_docker_compose + timeout-minutes: 20 + env: + SPIFFWORKFLOW_BACKEND_LOAD_FIXTURE_DATA: "true" + SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME: "acceptance_tests.yml" + - name: start_frontend + # working-directory: ./spiffworkflow-frontend + run: ./bin/build_and_run_with_docker_compose + - name: wait_for_backend + working-directory: ./spiffworkflow-backend + run: ./bin/wait_for_server_to_be_up 5 + - name: wait_for_frontend + # working-directory: ./spiffworkflow-frontend + run: ./bin/wait_for_frontend_to_be_up 5 + - name: wait_for_keycloak + working-directory: ./spiffworkflow-backend + run: ./bin/wait_for_keycloak 5 + - name: Cypress run + uses: cypress-io/github-action@v4 + with: + working-directory: ./spiffworkflow-frontend + browser: chrome + # only record on push, not pull_request, since we do not have secrets for PRs, + # so the required CYPRESS_RECORD_KEY will not be available. + record: ${{ github.event_name == 'push' }} + env: + # pass the Dashboard record key as an environment variable + CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} + # pass GitHub token to allow accurately detecting a build vs a re-run build + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: get_backend_logs_from_docker_compose + if: failure() + working-directory: ./spiffworkflow-backend + run: ./bin/get_logs_from_docker_compose >./log/docker_compose.log + - name: Upload logs + if: failure() + uses: "actions/upload-artifact@v3.0.0" + with: + name: spiffworkflow-backend-logs + path: "./spiffworkflow-backend/log/*.log" + + # https://github.com/cypress-io/github-action#artifacts + - name: upload_screenshots + uses: actions/upload-artifact@v2 + if: failure() + with: + name: cypress-screenshots + path: ./spiffworkflow-frontend/cypress/screenshots + # Test run video was always captured, so this action uses "always()" condition + - name: upload_videos + uses: actions/upload-artifact@v2 + if: failure() + with: + name: cypress-videos + path: ./spiffworkflow-frontend/cypress/videos diff --git a/spiffworkflow-frontend/cypress/e2e/tasks.cy.js b/spiffworkflow-frontend/cypress/e2e/tasks.cy.js index 6f34fefd..e755a590 100644 --- a/spiffworkflow-frontend/cypress/e2e/tasks.cy.js +++ b/spiffworkflow-frontend/cypress/e2e/tasks.cy.js @@ -13,6 +13,15 @@ const checkTaskHasClass = (taskName, className) => { cy.get(`g[data-element-id=${taskName}]`).should('have.class', className); }; +const kickOffModelWithForm = (modelId, formName) => { + cy.navigateToProcessModel( + 'Acceptance Tests Group One', + 'Acceptance Tests Model 2', + 'acceptance-tests-model-2' + ); + cy.runPrimaryBpmnFile(true); +}; + describe('tasks', () => { beforeEach(() => { cy.login(); @@ -107,21 +116,15 @@ describe('tasks', () => { cy.contains('Status: complete'); }); - // it('can paginate items', () => { - // cy.navigateToProcessModel( - // 'Acceptance Tests Group One', - // 'Acceptance Tests Model 1', - // 'acceptance-tests-model-1' - // ); - // - // // make sure we have some tasks - // cy.runPrimaryBpmnFile(); - // cy.runPrimaryBpmnFile(); - // cy.runPrimaryBpmnFile(); - // cy.runPrimaryBpmnFile(); - // cy.runPrimaryBpmnFile(); - // - // cy.navigateToHome(); - // cy.basicPaginationTest(); - // }); + it('can paginate items', () => { + // make sure we have some tasks + kickOffModelWithForm(); + kickOffModelWithForm(); + kickOffModelWithForm(); + kickOffModelWithForm(); + kickOffModelWithForm(); + + cy.navigateToHome(); + cy.basicPaginationTest(); + }); }); diff --git a/spiffworkflow-frontend/cypress/support/commands.js b/spiffworkflow-frontend/cypress/support/commands.js index a5937199..6b0e59a3 100644 --- a/spiffworkflow-frontend/cypress/support/commands.js +++ b/spiffworkflow-frontend/cypress/support/commands.js @@ -32,9 +32,8 @@ Cypress.Commands.add('getBySel', (selector, ...args) => { }); Cypress.Commands.add('navigateToHome', () => { - cy.get('button[aria-label="Open menu"]').click(); + cy.getBySel('header-menu-expand-button').click(); cy.getBySel('side-nav-items').contains('Home').click(); - // cy.getBySel('nav-home').click(); }); Cypress.Commands.add('navigateToAdmin', () => { @@ -85,14 +84,21 @@ Cypress.Commands.add('createModel', (groupId, modelId, modelDisplayName) => { cy.contains(`Process Model: ${modelDisplayName}`); }); -Cypress.Commands.add('runPrimaryBpmnFile', (reload = true) => { - cy.contains('Run').click(); - if (reload) { - cy.contains(/Process Instance.*kicked off/); - cy.reload(true); - cy.contains(/Process Instance.*kicked off/).should('not.exist'); +Cypress.Commands.add( + 'runPrimaryBpmnFile', + (expectAutoRedirectToHumanTask = false) => { + cy.contains('Run').click(); + if (expectAutoRedirectToHumanTask) { + // the url changes immediately, so also make sure we get some content from the next page, "Task:", or else when we try to interact with the page, it'll re-render and we'll get an error with cypress. + cy.url().should('include', `/tasks/`); + cy.contains('Task: '); + } else { + cy.contains(/Process Instance.*kicked off/); + cy.reload(true); + cy.contains(/Process Instance.*kicked off/).should('not.exist'); + } } -}); +); Cypress.Commands.add( 'navigateToProcessModel', diff --git a/spiffworkflow-frontend/src/components/NavigationBar.tsx b/spiffworkflow-frontend/src/components/NavigationBar.tsx index cc7137fb..fb482cd4 100644 --- a/spiffworkflow-frontend/src/components/NavigationBar.tsx +++ b/spiffworkflow-frontend/src/components/NavigationBar.tsx @@ -177,6 +177,7 @@ export default function NavigationBar() {