From 8f8c1e227efba3901b85e2d5033e1fb4488e994f Mon Sep 17 00:00:00 2001 From: Lynda L <29248132+ninjagirl888@users.noreply.github.com> Date: Wed, 30 Oct 2024 14:32:01 +0000 Subject: [PATCH] 8157 reinstate cypress nx plugin info (#564) * reinstate cypress nx info part 1 * Resinstated deleted Cypress files Update exisitng documentation with info about deprecation rather than deleting it. * Adding navigation back in. Removing
from table cell as build errors. * resinstaing asciidoc equivalent files for delete cypress plugin * updated files with improvements to deprecation information * updated: add a statement that was in the adoc file but not in md. * added spell check words for cypress back in following review * add image file back in * reinstated images back * adding newline to end eof * linting fix * linting fix - added newline to eof --- .spelling | 4 + .../azure-test-pipeline-summary-cypress.png | Bin 0 -> 52830 bytes ...ure-test-pipeline-test-results-cypress.png | Bin 0 -> 48925 bytes .../testing/testing_in_nx/cypress/_index.adoc | 6 + .../cypress_accessibility_testing.adoc | 191 ++++++++++++++ .../testing_in_nx/cypress/cypress_nx.adoc | 247 +++++++++++++++++ .../testing_in_nx/frontend_testing_in_nx.adoc | 5 +- .../azure/frontend/getting_started.adoc | 8 + .../plugins/cypress/accessibility.adoc | 55 ++++ .../frontend/plugins/cypress/executor.adoc | 24 ++ .../plugins/cypress/init-deployment.adoc | 68 +++++ .../azure/frontend/plugins/cypress/init.adoc | 61 +++++ .../plugins/cypress/plugin-information.adoc | 68 +++++ .../cypress/_init-deployment.md | 52 ++++ docs/getting_started/cypress/accessibility.md | 53 ++++ docs/getting_started/cypress/executor.md | 22 ++ docs/getting_started/cypress/init.md | 57 ++++ .../cypress/plugin-information.md | 83 ++++++ docs/getting_started/setup.md | 2 + .../cypress_accessibility_testing.md | 187 +++++++++++++ docs/testing/testing_in_nx/cypress_nx.md | 248 ++++++++++++++++++ .../testing_in_nx/frontend_testing_in_nx.md | 3 + docusaurus.config.js | 1 + sidebars.js | 9 + 24 files changed, 1453 insertions(+), 1 deletion(-) create mode 100644 asciidoc/images/azure-test-pipeline-summary-cypress.png create mode 100644 asciidoc/images/azure-test-pipeline-test-results-cypress.png create mode 100644 asciidoc/testing/testing_in_nx/cypress/_index.adoc create mode 100644 asciidoc/testing/testing_in_nx/cypress/cypress_accessibility_testing.adoc create mode 100644 asciidoc/testing/testing_in_nx/cypress/cypress_nx.adoc create mode 100644 asciidoc/workloads/azure/frontend/plugins/cypress/accessibility.adoc create mode 100644 asciidoc/workloads/azure/frontend/plugins/cypress/executor.adoc create mode 100644 asciidoc/workloads/azure/frontend/plugins/cypress/init-deployment.adoc create mode 100644 asciidoc/workloads/azure/frontend/plugins/cypress/init.adoc create mode 100644 asciidoc/workloads/azure/frontend/plugins/cypress/plugin-information.adoc create mode 100644 docs/getting_started/cypress/_init-deployment.md create mode 100644 docs/getting_started/cypress/accessibility.md create mode 100644 docs/getting_started/cypress/executor.md create mode 100644 docs/getting_started/cypress/init.md create mode 100644 docs/getting_started/cypress/plugin-information.md create mode 100644 docs/testing/testing_in_nx/cypress_accessibility_testing.md create mode 100644 docs/testing/testing_in_nx/cypress_nx.md diff --git a/.spelling b/.spelling index d14c1081b..a2f46406d 100644 --- a/.spelling +++ b/.spelling @@ -311,15 +311,19 @@ Commitlint - ./docs/nx/azure-node/app-insights-deployment.md APPLICATIONINSIGHTS_CONNECTION_STRING applicationinsightsConnectionString + - ./docs/nx/cypress/plugin-information.md InitGenerator InitDeploy AccessibilityGenerator accessibility.md executor.md + - ./docs/testing/testing_in_nx/cypress_accessibility_testing.md webpage spec e2e.ts + - ./docs/testing/testing_in_nx/cypress_nx.md localhost +cypress.config.base.ts mocha-junit-reporter JUnit-style junit-report diff --git a/asciidoc/images/azure-test-pipeline-summary-cypress.png b/asciidoc/images/azure-test-pipeline-summary-cypress.png new file mode 100644 index 0000000000000000000000000000000000000000..b3e542758dc9a318c3213a25a1f1950fca1a95e6 GIT binary patch literal 52830 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

%17`SA% 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 literal 0 HcmV?d00001 diff --git a/asciidoc/images/azure-test-pipeline-test-results-cypress.png b/asciidoc/images/azure-test-pipeline-test-results-cypress.png new file mode 100644 index 0000000000000000000000000000000000000000..0071d6b6150427929bdbabcb37fe043c11aa6e47 GIT binary patch literal 48925 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 z


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 { + beforeEach(() => { + cy.visit('/'); + cy.injectAxe(); + }); + + it('Has no detectable a11y violations on load (with custom parameters)', () => { + // Test the page at initial load (with context and options) + cy.checkA11y( + null, + { + runOnly: { + type: 'tag', + values: ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'], + }, + }, + terminalLogAxe + ); + }); + + it('Has no detectable a11y violations on load (filtering to only include critical impact violations)', () => { + // Test on initial load, only report and assert for critical impact items + cy.checkA11y( + null, + { + includedImpacts: ['critical'], + }, + terminalLogAxe + ); + }); + + // Basic usage after interacting with the page + it('Has no a11y violations after button click', () => { + // Interact with the page, then check for a11y issues + cy.contains('a', "What's next?").click(); + cy.checkA11y(null, undefined, terminalLogAxe); + }); + + it('Only logs a11y violations while allowing the test to pass', () => { + // Do not fail the test when there are accessibility failures + cy.checkA11y(null, undefined, terminalLogAxe, true); + }); + + it('Has no a11y violations after asynchronous load', () => { + // Retry the check if there are initial failures + cy.checkA11y( + null, + { + retries: 3, + interval: 100, + }, + terminalLogAxe + ); + }); +}); +---- + +Using `cypress-axe` we first inject `axe-core` into the webpage within our _beforeEach_ hook, this ensures that each test in the spec file has been set up to run tests using the axe testing engine. + +[source,typescript] +---- +beforeEach(() => { + cy.visit('/'); + // highlight-next-line + cy.injectAxe(); +}); +---- + +Using the `cy.checkA11y()` function (link:https://github.com/component-driven/cypress-axe/blob/master/README.md[see docs for usage]) we then test the webpage against various accessibility rules. + +[source,typescript] +---- +it('Has no detectable a11y violations on load (with custom parameters)', () => { + // Test the page at initial load (with context and options) + cy.checkA11y( + null, + { + // highlight-start + runOnly: { + type: 'tag', + values: ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'], + }, + // highlight-end + }, + terminalLogAxe + ); + +}); +---- + +Passing the `terminalLogAxe` function as a callback to `cy.checkA11y()` then creates and prints a readable table of accessibility violations to the console. (The `terminalLogAxe` function has been added to your _app-name/cypress/support/e2e.ts_ file) + +[source,typescript] +---- +it('Has no detectable a11y violations on load (with custom parameters)', () => { + // Test the page at initial load (with context and options) + cy.checkA11y( + null, + { + runOnly: { + type: 'tag', + values: ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'], + }, + }, + // highlight-next-line + terminalLogAxe + ); +}); +---- + +=== Running your accessibility tests + +We recommend tagging your Cypress accessibility tests so that you can target these specific tests if required. In the below examples we have tagged the tests with **@accessibility** which enables us to target them through **grep** as seen in the link:./cypress_nx.adoc#run-specific-tests['Run specific tests'] example + +.GROUPED +[%collapsible] +===== +[source,typescript] +---- + //multiple tests grouped in a describe block + describe('Example test group @accessibility', () => { + + it('accessibility test 1', async ({ page }) => { + //test code + }); + + it('accessibility test 2', async ({ page }) => { + //test code + }); + } +---- +===== + +.INDIVIDUAL +[%collapsible] +===== +[source,typescript] +---- +it('Example individual test @accessibility', () => { + //Accessibility test with axe +}); +---- +===== + +== Viewing your test results + +Further to the explanation given in the link:./cypress_nx.adoc#running-your-cypress-tests['Testing with Cypress'] page, accessibility test results can also be found in the console output post execution. + +.Sample AXE report +[%nowrap,bash] +---- +1) Has no detectable a11y violations on load (with custom parameters) +3 accessibility violations were detected +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β” +β”‚ (index) β”‚ id β”‚ impact β”‚ description β”‚ nodes β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ 0 β”‚ 'color-contrast' β”‚ 'serious' β”‚ 'Ensures the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds' β”‚ 1 β”‚ +β”‚ 1 β”‚ 'html-has-lang' β”‚ 'serious' β”‚ 'Ensures every HTML document has a lang attribute' β”‚ 1 β”‚ +β”‚ 2 β”‚ 'svg-img-alt' β”‚ 'serious' β”‚ 'Ensures elements with an img, graphics-document or graphics-symbol role have an accessible text' β”‚ 3 β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”˜ +---- diff --git a/asciidoc/testing/testing_in_nx/cypress/cypress_nx.adoc b/asciidoc/testing/testing_in_nx/cypress/cypress_nx.adoc new file mode 100644 index 000000000..f965d0453 --- /dev/null +++ b/asciidoc/testing/testing_in_nx/cypress/cypress_nx.adoc @@ -0,0 +1,247 @@ +--- +id: testing_with_cypress +title: Testing with Cypress +linkTitle: Testing with cypress +weight: 1 +keywords: + - NX + - testing + - cypress + - cross-browser +--- + +:imagesdir: ../../../../images + +== Overview + +Cypress is a powerful testing framework that has gained popularity for its robust features and ease of use. Developed and maintained by a dedicated community, Cypress offers a comprehensive solution for web automation testing. It focuses on providing a seamless cross-browser experience, allowing developers to write reliable and efficient tests across different browsers. Due to its popularity, we are supporting it as a test framework within Ensono Stacks! + +== Getting Started + +Upon scaffolding your application with the Cypress testing framework, you will be presented with an example test suite and cypress configuration. The link:https://www.npmjs.com/package/@nx/cypress[`@nx/cypress`] NX plugin is used as a base for the Cypress/NX integration. + +== Cypress Configuration + +=== Base Configuration [[base-configuration]] + +The base configuration has been created with CI in mind, meaning the default configuration (shared across all projects) considers requirements for reporting and pipeline efficiency out of the box! This is created at the root of the project workspace and is used as the basis for each applications unique configuration. + +.cypress.config.base.ts +[source,typescript] +---- +import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset'; + +const appName = process.env.NX_TASK_TARGET_PROJECT as string; +const outputFolderForProject = process.env.CI + ? `../../test-results/${appName}` + : 'cypress/test-results'; +const baseURL = process.env.BASE_URL || 'http://localhost:4200/'; +export const baseConfig: Cypress.ConfigOptions = { + // Test reporting configured with multiple reporters + reporter: '../../node_modules/cypress-multi-reporters', + // Spec: CI/Local (Default logging to console) + // mocha-j单位nit-reporter: CI (JUnit XML reports for CI reporting) + // mochawesome: CI (Used for HTML report generation) + // Reports saved to asset folders to utilize automated 'trashAssets' mechanism + reporterOptions: { + reporterEnabled: !process.env.CI + ? 'spec' + : 'spec, mocha-junit-reporter, mochawesome', + mochaJunitReporterReporterOptions: { + mochaFile: outputFolderForProject.concat( + '/downloads/junit-report/results-[hash].xml' + ), + }, + // Mocha configuration for html reporting + mochawesomeReporterOptions: { + charts: true, + overwrite: false, + html: false, // set to false as will be generated during consolidation of json files + json: true, + reportDir: outputFolderForProject.concat('/downloads/reports-json-file'), + reportFilename: '[name].html', + embeddedScreenshots: true, + inlineAssets: true, + }, + }, + // Configuration for e2e tests + e2e: { + ...nxE2EPreset(__dirname, { cypressDir: 'cypress' }), + baseUrl: baseURL, + // All assets directed into output folder + screenshotsFolder: outputFolderForProject.concat('/screenshots'), + videosFolder: outputFolderForProject.concat('/videos'), + downloadsFolder: outputFolderForProject.concat('/downloads'), + videoUploadOnPasses: false, + // Assets, including html reports, trashed before each run + trashAssetsBeforeRuns: true, + retries: { + runMode: process.env.CI ? 2 : 0, + }, + // Configure Cypress grep + setupNodeEvents(on, config) { + require('@cypress/grep/src/plugin')(config); + return config; + }, + }, +}; +---- + +=== Project-based Configuration [[project-based-configuration]] + +Within the application where Cypress has been added, a Cypress configuration file for that specific application will have been created. Extending the <>, this file can be used to add or change the default workspace configuration for Cypress! See the official link:https://docs.cypress.io/guides/references/configuration[Cypress docs] for more information on configuring your test project! + +[source,typescript] +---- +import { defineConfig } from 'cypress'; + +import { baseConfig } from '../../cypress.config.base'; + +export default defineConfig({ + ...baseConfig, + e2e: { + ...baseConfig.e2e, + screenshotOnRunFailure: true, + video: true, + }, +}); +---- +== Testing + +=== Writing Tests + +When building your Cypress tests, it helps to have a version of the application deployed for capturing locators and verifying your tests function as intended. + +You can serve your required application to localhost on port 4200 through the following command: + +[source,shell] +---- +nx serve +---- + +NX will then build and host your application, allowing you to build/run your tests against a usable version of the application. + +[source,shell] +---- +nx serve next-app + +> nx run next-app:serve:development + + info - automatically enabled Fast Refresh for 1 custom loader + event - compiled client and server successfully in 8.5s (166 modules) + [ ready ] on http://localhost:4200 +---- + +== Running Your Cypress Tests + +Using NX, you can easily run your tests, either for a specific project or against any affected projects. NX will handle provisioning and tearing down of the web server automatically! Using the NX 'affected' capability allows you to run only the tests within a monorepo where the codebase has changes since the 'master' commit. (See the link:https://nx.dev/concepts/affected[docs] for more information) + +.CURRENT +---- +nx e2e +---- + +.AFFECTED +---- +nx affected:e2e +---- + +=== Run Specific Tests + +Looking at the following example, we have tagged the test with **@smoke-test** within the test case name: + +[source,typescript] +---- +it('should be up and running @smoke-test', () => { + cy.get('#hero').find('span').should('have text', "You're up and running"); +}); +---- + +We utilize link:https://www.npmjs.com/package/@cypress/grep[@cypress/grep] to enable you to run this specific test. By specifying the grep parameter with the **@smoke-test** value alongside your run command, this specific test will be executed. Similarly, if multiple tests contain **@smoke-test** within their name, they will also be executed. + +[source,shell] +---- +nx e2e --env.grep="@smoke-test" +---- + +== Testing Output + +=== Viewing Your Test Results + +Cypress has many configuration options for test reporting, which can be found in link:https://docs.cypress.io/guides/tooling/reporters[the documentation]. + +=== Locally + +Using the scaffolded <>, all test results will be output to the terminal using Cypress **_spec_** reporter. An example output can be seen below: + +[source,shell] +---- +Cypress example tests @example-cypress + - should take the user to the next steps part of the page when clicking whats next + √ App should be up and running @smoke + - App should have 5 learning materials @integration +1 passing (1s) +2 pending +(Results) +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Tests: 3 β”‚ +β”‚ Passing: 1 β”‚ +β”‚ Failing: 0 β”‚ +β”‚ Pending: 2 β”‚ +β”‚ Skipped: 0 β”‚ +β”‚ Screenshots: 0 β”‚ +β”‚ Video: false β”‚ +β”‚ Duration: 1 second β”‚ +β”‚ Spec Ran: example.cy.ts β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +==================================================================================================== +(Run Finished) + Spec Tests Passing Failing Pending Skipped +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ βœ” example.cy.ts 00:01 3 1 - 2 - β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +βœ” All specs passed! 00:01 3 1 - 2 - + +> NX Successfully ran target e2e for project next-cypress-application (29s) + + With additional flags: + --env={"grep":"@smoke"} +---- + +To change the reporter being used locally, you can amend the <> to overwrite the reporter definition in the [cypress.config.base.ts](#base-configuration), view the link:https://docs.cypress.io/guides/tooling/reporters[Cypress documentation] for further information! + +=== Output in CI + +[NOTE] +==== +The following plugins are dependencies for adding Cypress to your build and deployment pipelines: + +* link:../../getting_started/workspace/plugin-information.adoc#generators[`@ensono-stacks/workspace:init`] +* link:../../getting_started/next/plugin-information.adoc#ensono-stacksnextinit-deployment[`@ensono-stacks/next:init-deployment`] +==== + +* Running the link:../../getting_started/cypress/plugin-information.adoc#ensono-stackscypressinit-deployment[`@ensono-stacks/cypress:init-deployment`] generator will configure your taskctl pipelines with the relevant test/reporting tasks. +* Upon a pull request being made, this will automatically trigger a build pipeline for your application whereby the e2e tests for the application will be ran. +* As defined in the <>, all test artifacts are output to 'test-results/' + +When running in the CI, three reporters are utilized: + +1. spec: Default Cypress console reporting. + +2. mocha-junit-reporter: A JUnit-style XML reports which are fed back into CI reports on the test run. Output to 'test-results//downloads/junit-report'. + +3. mochawesome: Reports for each test which are used as the basis for HTML report generation. Output to 'test-results//downloads/reports-json-file'. + +== Build Summary + +You can view a summary of your build by viewing the pipeline which was ran upon pull request creation. + +image::azure-test-pipeline-summary-cypress.png[Azure Pipeline Summary] + +**Test results:** As part of your generated pipelines test results will be automatically displayed within the summary tab for the build. + +image::azure-test-pipeline-test-results-cypress.png[Azure Pipeline Test Results] + +**Test artefacts:** To download the test artefacts captured by Cypress select the _build_ job on the summary page, within the build log click on the 'artefact produced' link, from here you can then download the 'testresults' folder for the test run. + +image::azure-test-pipeline-build-log.png[Azure Pipeline Build log] \ No newline at end of file diff --git a/asciidoc/testing/testing_in_nx/frontend_testing_in_nx.adoc b/asciidoc/testing/testing_in_nx/frontend_testing_in_nx.adoc index c145a6618..1d2114d2e 100644 --- a/asciidoc/testing/testing_in_nx/frontend_testing_in_nx.adoc +++ b/asciidoc/testing/testing_in_nx/frontend_testing_in_nx.adoc @@ -7,6 +7,7 @@ keywords: - Nx - testing - playwright + - cypress - accessibility testing - visual regression testing - monorepo @@ -20,7 +21,9 @@ To leverage Ensono Stacks and accelerate your testing process within your Nx mon === Selecting your test framework -We recommend and currently support Playwright within the Ensono Stacks workflow. With its Microsoft backing, extensive feature set, and fast cross-browser web automation capability, it is our preferred tooling choice. +We recommend and currently support Playwright within the Ensono Stacks workflow. With its Microsoft backing, extensive feature set, and fast cross-browser web automation capability, it is our preferred tooling choice. + +However, existing users can still find information about the deprecated Cypress plugin link:../../getting_started/cypress/plugin-information.adoc[here]. TIP: Visit the link:../../getting_started/playwright/plugin-information.adoc[`Playwright`] Ensono Stacks plugins to start testing! diff --git a/asciidoc/workloads/azure/frontend/getting_started.adoc b/asciidoc/workloads/azure/frontend/getting_started.adoc index 81df2e211..0b4c266a0 100644 --- a/asciidoc/workloads/azure/frontend/getting_started.adoc +++ b/asciidoc/workloads/azure/frontend/getting_started.adoc @@ -118,6 +118,14 @@ a|Add the playwright testing library and much more to your project! - Add visual testing with Applitools eyes - Add playwright testing and reporting automatically to your build pipelines +|link:./cypress/plugin-information.md[`@ensono-stacks/cypress`] +a|**Deprecated: This plugin is no longer supported. Ensono-stacks/cypress-2.0.7 is the final release version and may not be compatible with the ensono-stacks/workspace plugin above version 2.0.7. Existing users can still find information about the deprecated Cypress plugin link:./cypress/plugin-information.md[here]** + +Add the cypress testing library and much more to your project! + +- Add accessibility testing to your test project +- Add cypress testing and reporting automatically to your build pipelines + |link:./logger/plugin-information.md[`@ensono-stacks/logger`] a|Add industry standard logging capabilities to your project diff --git a/asciidoc/workloads/azure/frontend/plugins/cypress/accessibility.adoc b/asciidoc/workloads/azure/frontend/plugins/cypress/accessibility.adoc new file mode 100644 index 000000000..eee9a1d2a --- /dev/null +++ b/asciidoc/workloads/azure/frontend/plugins/cypress/accessibility.adoc @@ -0,0 +1,55 @@ +=== @ensono-stacks/cypress:accessibility + +.Adds axe accessibility tests to your test project +[%collapsible] +===== +[.details] +==== +The _accessibility_ generator installs the required plugins for conducting accessibility testing with Cypress. Additionally, this will configure your test project to enable proper test reporting from `axe` while providing you with an example set of test cases. +==== + +[discrete] +== Usage + +---- +nx g @ensono-stacks/cypress:accessibility +---- + +[discrete] +== Command line arguments + +[cols="1,1"] +|=== +| Option | Description + +| --project -p +| The name of the test project to add accessibility tests to +|=== + +[discrete] +== Generator Output + +Scaffolding accessibility testing will add two dependencies to the `package.json`: + +1. link:https://www.npmjs.com/package/axe-core[`axe-core`] - The accessibility test engine +2. link:https://www.npmjs.com/package/cypress-axe[`cypress-axe`] - Cypress integration with the accessibility test engine + +Additionally, an example accessibility test will be generated, showcasing how to utilize _axe_ to scan your application for accessibility violations: + +[source,text] +---- +. +β”œβ”€β”€ apps +β”‚ β”œβ”€β”€ +β”‚ β”‚ β”œβ”€β”€ cypress +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ support +β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ e2e.ts #Terminal logging function configured +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ e2e +β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ axe-accessibility.cy.ts #Example accessibility test using cypress +β”‚ β”œβ”€β”€ cypress.config.js #setupNodeEvents configured for logging with terminal logging function +β”œβ”€β”€ tsconfig.cy.json #cypress-axe declared as a type +└────────── +---- + +NOTE: Visit the link:../../testing/testing_in_nx/cypress_accessibility_testing.adoc[Accessibility Testing] documentation for further details! +===== \ No newline at end of file diff --git a/asciidoc/workloads/azure/frontend/plugins/cypress/executor.adoc b/asciidoc/workloads/azure/frontend/plugins/cypress/executor.adoc new file mode 100644 index 000000000..d8e0273b1 --- /dev/null +++ b/asciidoc/workloads/azure/frontend/plugins/cypress/executor.adoc @@ -0,0 +1,24 @@ +=== @nx/cypress:cypress + +.Enables you to execute your Cypress tests +[%collapsible] +===== +[.details] +==== +The _cypress_ executor is an executor provided by `@nx/cypress` and enables you to run your E2E tests. +==== + +[discrete] +== Usage + +The following command will run all of the Cypress tests within your application's Cypress test folder. As part of the executor, it will automatically spin up a web server on localhost for the corresponding application. + +---- +nx e2e +---- + +[discrete] +== Command line arguments + +See the link:https://nx.dev/packages/cypress/executors/cypress[@nx/cypress] plugin page for a list of up-to-date command line arguments. +===== \ No newline at end of file diff --git a/asciidoc/workloads/azure/frontend/plugins/cypress/init-deployment.adoc b/asciidoc/workloads/azure/frontend/plugins/cypress/init-deployment.adoc new file mode 100644 index 000000000..951185992 --- /dev/null +++ b/asciidoc/workloads/azure/frontend/plugins/cypress/init-deployment.adoc @@ -0,0 +1,68 @@ +=== @ensono-stacks/cypress:init-deployment + +.Create cypress E2E tests to your deployment pipelines +[%collapsible] +===== +[.details] +==== +The _init-deployment_ generator adds E2E testing to pre-existing deployment pipelines, including test reporting and artifact uploads. +==== + +[discrete] +== Prerequisites + +1. The link:../workspace/plugin-information.adoc[@ensono-stacks/workspace:init-deployment] has been executed, producing the required deployment files for the workspace + +[discrete] +== Usage + +---- +nx g @ensono-stacks/cypress:init-deployment +---- + +[discrete] +== Generator Output + +[source,yaml] +---- +# New e2e:ci task definition will be added to the tasks.yaml, defining what target should be ran for projects when executing the e2e task +e2e:ci: + description: Run e2e tests in ci + command: + - npx nx affected --base="$BASE_SHA" --target=e2e --parallel=1 +---- + +NOTE: The `e2e:ci` task definition will be added to the tasks.yaml file, defining the target to run for projects when executing the E2E task. + +[source,yaml] +---- +# New e2e:ci task will be added to the taskctl pipeline, adding e2e tests following unit testing +- task: e2e:ci + depends_on: test:ci +---- + +NOTE: A new `e2e:ci` task will be added to the taskctl pipeline, adding E2E tests following unit testing. + +[source,yaml] +---- +# Generate HTML report for all affected projects +- task: Bash@3 + condition: and(succeededOrFailed(),eq(variables.HASTESTRESULTS, 'true')) + displayName: Generate Reports + inputs: + targetType: inline + script: npx nx affected --base="$BASE_SHA" --target=html-report + --configuration=ci --parallel=1 +# New test reporting steps will be added to the azuredevops pipeline +- task: PublishTestResults@2 + # Configuration for publishing test results +- task: PublishPipelineArtifact@1 + # Configuration for publishing pipeline artifacts +---- + +[NOTE] +==== +- Generate an HTML report for all affected projects. +- New test reporting steps will be added to the Azure DevOps pipeline. +==== +===== \ No newline at end of file diff --git a/asciidoc/workloads/azure/frontend/plugins/cypress/init.adoc b/asciidoc/workloads/azure/frontend/plugins/cypress/init.adoc new file mode 100644 index 000000000..b6513cce4 --- /dev/null +++ b/asciidoc/workloads/azure/frontend/plugins/cypress/init.adoc @@ -0,0 +1,61 @@ +=== @ensono-stacks/cypress:init + +.Create a cypress test project for your chosen application +[%collapsible] +===== +[.details] +==== +The _init_ generator adds cypress e2e tests to the application you choose. +==== + +[discrete] +== Usage + +---- +nx g @ensono-stacks/cypress:init +---- + +Upon calling the _init_ generator, you will be presented with the following question: + +- What app would you like to generate a test project for? + - The name of the existing application to generate a test project for + +[discrete] +== Command line arguments + +The following command line arguments are available: + +[cols="1,1"] +|=== +| Option | Description + +| --project +| The name of the application to generate a test project for +|=== + +[discrete] +== Generator Output + +The _init_ generator will create a new test project within your chosen application containing an example test and predefined configuration for the monorepo and the individual test project. + +.Generated files +---- +. +β”œβ”€β”€ apps +β”‚ β”œβ”€β”€ +β”‚ β”‚ β”œβ”€β”€ cypress +β”‚ β”‚ β”‚ β”œβ”€β”€ e2e +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ example.cy.ts #Example tests using cypress +β”‚ β”‚ β”‚ β”œβ”€β”€ fixtures +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ example.json #Example fixture/test data +β”‚ β”‚ β”‚ β”œβ”€β”€ support +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ commands.ts #Example custom commands for cypress +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ e2e.ts #Configuration for cypress and test reporting +β”‚ β”‚ β”‚ β”œβ”€β”€ tsconfig.json #Typescript configuration for cypress +β”‚ β”‚ β”œβ”€β”€ project.json #Updated with target for cypress and reporting +β”‚ β”‚ β”œβ”€β”€ tsconfig.json #Typescript configuration updated for cypress exclusions +└── cypress.config.base.ts #Shared cypress configuration across projects +---- + +NOTE: Visit the link:../../testing/testing_in_nx/cypress_nx.adoc[Testing with cypress] documentation for further details! +===== \ No newline at end of file diff --git a/asciidoc/workloads/azure/frontend/plugins/cypress/plugin-information.adoc b/asciidoc/workloads/azure/frontend/plugins/cypress/plugin-information.adoc new file mode 100644 index 000000000..19ea995c2 --- /dev/null +++ b/asciidoc/workloads/azure/frontend/plugins/cypress/plugin-information.adoc @@ -0,0 +1,68 @@ +--- +id: ensono-stacks-cypress +title: "@ensono-stacks/cypress" +linkTitle: "@ensono-stacks/cypress" +weight: 8 +keywords: + - Nx + - monorepo + - stacks + - ensono + - cypress + - generator + - executor +--- + +[IMPORTANT] +==== +Deprecated + +This plugin is no longer supported. Ensono-stacks/cypress 2.0.7 is the final release version and may not be compatible with the ensono-stacks/workspace plugin above version 2.0.7. Existing users can still find information about the deprecated Cypress plugin here. +==== + +Using the `@ensono-stacks/cypress` plugin can help you get started with testing using Cypress. Built upon the link:https://nx.dev/packages/cypress[@nx/cypress] plugin, Ensono Stacks provides additional capabilities to help you hit the ground running! + +Additionally, Cypress tests can be added to your deployment pipelines through the various deployment generators. + +NOTE: Visit the link:../../testing/testing_in_nx/frontend_testing_in_nx.md[Frontend Testing in an Nx monorepo] and link:../../testing/testing_in_nx/cypress_nx.md[Testing with Cypress] user guides for more information! + + +== Setting up @ensono-stacks/cypress + +Install the `@ensono-stacks/cypress` plugin with the following command: + +---- +npm install --save-dev @ensono-stacks/cypress@latest +---- + +or + +---- +yarn add --dev @ensono-stacks/cypress@latest +---- + +== Executors and Generators + +To see a list of the plugin capabilities, run the following command: + +---- +nx list @ensono-stacks/cypress +---- + +View additional information about a plugin capability through the following command: + +---- +nx g @ensono-stacks/cypress:[generator-executor-name] --help +---- + +=== Generators + +include::init.adoc[] + +include::init-deployment.adoc[] + +include::accessibility.adoc[] + +=== Executors + +include::executor.adoc[] \ No newline at end of file diff --git a/docs/getting_started/cypress/_init-deployment.md b/docs/getting_started/cypress/_init-deployment.md new file mode 100644 index 000000000..a5f15dc6d --- /dev/null +++ b/docs/getting_started/cypress/_init-deployment.md @@ -0,0 +1,52 @@ + +### @ensono-stacks/cypress:init-deployment + +
+Add cypress E2E tests to your deployment pipelines + +The _init-deployment_ generator adds e2e testing to pre-existing deployment pipelines, including test reporting and artefact uploads. + +## Prerequisites + +1. The [@ensono-stacks/workspace:init-deployment](../workspace/plugin-information.md#ensono-stacksworkspaceinit-deployment) has been executed, producing the required deployment files for the workspace + +## Usage + +```bash +nx g @ensono-stacks/cypress:init-deployment +``` + +### Generator Output + +```yaml title=build/taskctl/tasks.yaml +# New e2e:ci task definition will be added to the tasks.yaml, defining what target should be ran for projects when executing the e2e task +e2e:ci: + description: Run e2e tests in ci + command: + - npx nx affected --base="$BASE_SHA" --target=e2e --parallel=1 +``` + +```yaml title=taskctl.yaml +# New e2e:ci task will be added to the taskctl pipeline, adding e2e tests following unit testing +- task: e2e:ci + depends_on: test:ci +``` + +```yaml build/azDevOps/azuredevops-stages.yaml +# Generate HTML report for all affected projects +- task: Bash@3 + condition: and(succeededOrFailed(),eq(variables.HASTESTRESULTS, 'true')) + displayName: Generate Reports + inputs: + targetType: inline + script: npx nx affected --base="$BASE_SHA" --target=html-report + --configuration=ci --parallel=1 +# New test reporting steps will be added to the azuredevops pipeline +- task: PublishTestResults@2 + # Configuration for publishing test results +- task: PublishPipelineArtifact@1 + # Configuration for publishing pipeline artefacts +``` + + +
diff --git a/docs/getting_started/cypress/accessibility.md b/docs/getting_started/cypress/accessibility.md new file mode 100644 index 000000000..e87812106 --- /dev/null +++ b/docs/getting_started/cypress/accessibility.md @@ -0,0 +1,53 @@ + + +### @ensono-stacks/cypress:accessibility {#ensono-stacks-cypress-accessibility} + +
+Adds axe accessibility tests to your test project + +The _accessibility_ generator installs the required plugins for conducting accessibility testing with cypress. Additionally, this will configure your test project to enable proper test reporting from `axe` while providing you with an example set of test cases. + +## Usage + +```bash +nx g @ensono-stacks/cypress:accessibility +``` + +### Command line arguments + +The following command line arguments are available: + +| Option | Description | Type | +| ------------ | ---------------------------------------------------------- | ------ | +| --project -p | The name of the test project to add accessibility tests to | string | + +### Generator Output + +Scaffolding accessibility testing will add two dependencies to the `package.json`: + +1. [`axe-core`](https://www.npmjs.com/package/axe-core) - The accessibility test engine +2. [`cypress-axe`](https://www.npmjs.com/package/cypress-axe) - Cypress integration with the accessibility test engine + +Additionally, an example accessibility test will be generated, showcasing how to utilise _axe_ to scan your application for accessibility violations: + +```text title="Generated files" +. +β”œβ”€β”€ apps +β”‚ β”œβ”€β”€ +β”‚ β”‚ β”œβ”€β”€ cypress +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ support +β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ e2e.ts #Terminal logging function configured +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ e2e +β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ axe-accessibility.cy.ts #Example accessibility test using cypress +β”‚ β”‚ β”œβ”€β”€ cypress.config.js #setupNodeEvents configured for logging with terminal logging function +β”œβ”€β”€ tsconfig.cy.json #cypress-axe declared as a type +└────────── +``` + +:::note + +Visit the [`Accessibility Testing`](../../testing/testing_in_nx/cypress_accessibility_testing.md) documentation for further details! + +::: + +
diff --git a/docs/getting_started/cypress/executor.md b/docs/getting_started/cypress/executor.md new file mode 100644 index 000000000..d638408bc --- /dev/null +++ b/docs/getting_started/cypress/executor.md @@ -0,0 +1,22 @@ + + +### @nx/cypress:cypress {#ensono-stacks-cypress-executor} + +
+Enables you to execute your cypress tests + +The _cypress_ executor is an executor provided by `@nx/cypress` and enables you to run your e2e tests. + +## Usage + +The following command will run all of the cypress tests within your applications cypress test folder, as part of the executor it will automatically spin up a web server on local host for the corresponding application. + +```bash +nx e2e +``` + +### Command line arguments + +See the [@nx/cypress](https://nx.dev/packages/cypress/executors/cypress) plugin page for a list of up to date command line arguments + +
diff --git a/docs/getting_started/cypress/init.md b/docs/getting_started/cypress/init.md new file mode 100644 index 000000000..e9d7788f5 --- /dev/null +++ b/docs/getting_started/cypress/init.md @@ -0,0 +1,57 @@ + + +### @ensono-stacks/cypress:init {#ensono-stacks-cypress-init} + +
+Create a cypress test project for your chosen application + +The _init_ generator adds cypress e2e tests to the application you choose. + +## Usage + +```bash +nx g @ensono-stacks/cypress:init +``` + +Upon calling the _init_ generator you will be presented with the following question: + +- What app would you like to generate a test project for? +- The name of the existing application to generate a test project for + +### Command line arguments + +The following command line arguments are available: + +| Option | Description | Type | +| --------- | ---------------------------------------------------------- | ------ | +| --project | The name of the application to generate a test project for | string | + +### Generator Output + +The _init_ generator will create a new test project within your chosen application containing an example test and predefined configuration for the monorepo and the individual test project. + +```text title="Generated files" +. +β”œβ”€β”€ apps +β”‚ β”œβ”€β”€ +β”‚ β”‚ β”œβ”€β”€ cypress +β”‚ β”‚ β”‚ β”œβ”€β”€ e2e +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ example.cy.ts #Example tests using cypress +β”‚ β”‚ β”‚ β”œβ”€β”€ fixtures +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ example.json #Example fixture/test data +β”‚ β”‚ β”‚ β”œβ”€β”€ support +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ commands.ts #Example custom commands for cypress +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ e2e.ts #Configuration for cypress and test reporting +β”‚ β”‚ β”‚ β”œβ”€β”€ tsconfig.json #Typescript configuration for cypress +β”‚ β”‚ β”œβ”€β”€ project.json #Updated with target for cypress and reporting +β”‚ β”‚ β”œβ”€β”€ tsconfig.json #Typescript configuration updated for cypress exclusions +└── cypress.config.base.ts #Shared cypress configuration across projects +``` + +:::note + +Visit the [`Testing with cypress`](../../testing/testing_in_nx/cypress_nx.md) documentation for further details! + +::: + +
diff --git a/docs/getting_started/cypress/plugin-information.md b/docs/getting_started/cypress/plugin-information.md new file mode 100644 index 000000000..f7bcca133 --- /dev/null +++ b/docs/getting_started/cypress/plugin-information.md @@ -0,0 +1,83 @@ +--- +id: ensono-stacks-cypress +title: "@ensono-stacks/cypress" +sidebar_label: "@ensono-stacks/cypress" +description: "Using cypress with Ensono Stacks!" +keywords: + - Nx + - monorepo + - stacks + - ensono + - cypress + - generator + - executor +--- + +:::caution Deprecated +This plugin is no longer supported. Ensono-stacks/cypress 2.0.7 is the final release version and may not be compatible with the ensono-stacks/workspace plugin above version 2.0.7. Existing users can still find information about the deprecated Cypress plugin here. +::: + +import InitGenerator from './init.md' + + + +import AccessibilityGenerator from './accessibility.md' +import Executor from './executor.md' +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +Using the `@ensono-stacks/cypress` plugin can help you get started with testing using cypress. Built upon the [@nx/cypress](https://nx.dev/packages/cypress) plugin, Ensono Stacks provides additional capabilities to help you hit the ground running! + +Additionally, cypress tests can be added to your deployment pipelines through the various deployment generators. + +:::tip + +Visit the [Frontend Testing in an Nx monorepo](../../testing/testing_in_nx/frontend_testing_in_nx.md) and [Testing with cypress](../../testing/testing_in_nx/cypress_nx.md) user guides for more information! + +::: + +## Setting up @ensono-stacks/cypress + +Install the `@ensono-stacks/cypress` plugin with the following command: + + + + +```bash +npm install --save-dev @ensono-stacks/cypress@latest +``` + + + + +```bash +yarn add --dev @ensono-stacks/cypress@latest +``` + + + + +## Executors and Generators + +To see a list of the plugin capabilities run the following command: + +```bash +nx list @ensono-stacks/cypress +``` + +View additional information about a plugin capability through the following command: + +```bash +nx g @ensono-stacks/cypress:[generator-executor-name] --help +``` + +### Generators + + + + + + +### Executors + + diff --git a/docs/getting_started/setup.md b/docs/getting_started/setup.md index 192d8b4e4..ef5cf18ad 100644 --- a/docs/getting_started/setup.md +++ b/docs/getting_started/setup.md @@ -8,6 +8,7 @@ keywords: - monorepo - stacks - ensono + - cypress - Generator - Executor --- @@ -109,6 +110,7 @@ To accelerate your project development and ensure consistency across those proje | `@ensono-stacks/azure-react` |
  • Coming soon!
  • Install and configure a ReactJS library with app insights
  • | | [`@ensono-stacks/rest-client`](./rest-client/plugin-information.md) | Add a rest client to a project in your Ensono Stacks workspace
  • Create an Axios http-client with custom configuration
  • Create a client endpoint with Axios HTTP methods for your application
  • Bump existing endpoints to new versions
  • Create code implementation from an OpenApi schema using Orval
  • | | [`@ensono-stacks/playwright`](./playwright/plugin-information.md) | Add the playwright testing library and much more to your project!
  • Create a playwright testing project for your application
  • Add accessibility testing to your test project
  • Add native visual testing with playwright
  • Add visual testing with Applitools eyes
  • Add playwright testing and reporting automatically to your build pipelines
  • | +| [`@ensono-stacks/cypress`](./cypress/plugin-information.md) | _**Deprecated: This plugin is no longer supported. Ensono-stacks/cypress-2.0.7 is the final release version and may not be compatible with the ensono-stacks/workspace plugin above version 2.0.7. Existing users can still find information about the deprecated Cypress plugin [here](./cypress/plugin-information.md)**_
  • Add the cypress testing library and much more to your project!
  • Add accessibility testing to your test project
  • Add cypress testing and reporting automatically to your build pipelines
  • | | [`@ensono-stacks/logger`](./logger/plugin-information.md) | Add industry standard logging capabilities to your project
  • Add Winston to your project
  • | ### Further Notes diff --git a/docs/testing/testing_in_nx/cypress_accessibility_testing.md b/docs/testing/testing_in_nx/cypress_accessibility_testing.md new file mode 100644 index 000000000..028aca2b7 --- /dev/null +++ b/docs/testing/testing_in_nx/cypress_accessibility_testing.md @@ -0,0 +1,187 @@ +--- +id: cypress_accessibility_testing +title: Accessibility Testing with Cypress +sidebar_label: Accessibility Testing +description: Accessibility Testing with Cypress using Axe! +keywords: + - NX + - axe + - tests + - testing + - cypress + - accessibility testing +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +Accessibility testing with Cypress is very simple and ensures that everyone, including those with disabilities or impairments can fully access and use the site or app. It is not only a legal requirement, but also a moral and ethical one, to ensure that digital products are inclusive and usable by all. + +## Axe: Accessibility testing + +From the Dequeue family of products, we are using [aXe](https://www.deque.com/axe/) for accessibility testing. Using their Node.js plugin, [`axe-core`](https://www.npmjs.com/package/axe-core), we also utilise [`cypress-axe`](https://www.npmjs.com/package/cypress-axe) for integration into the Cypress testing framework. + +### Scaffolded Example + +When accessibility tests are scaffolded into your project you will see the following example: + +```typescript title="axe-accessibility.cy.ts" +import 'cypress-axe'; +import { terminalLogAxe } from '../support/e2e'; + +describe('@accessibility-tests', () => { + beforeEach(() => { + cy.visit('/'); + cy.injectAxe(); + }); + + it('Has no detectable a11y violations on load (with custom parameters)', () => { + // Test the page at initial load (with context and options) + cy.checkA11y( + null, + { + runOnly: { + type: 'tag', + values: ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'], + }, + }, + terminalLogAxe + ); + }); + + it('Has no detectable a11y violations on load (filtering to only include critical impact violations)', () => { + // Test on initial load, only report and assert for critical impact items + cy.checkA11y( + null, + { + includedImpacts: ['critical'], + }, + terminalLogAxe + ); + }); + + // Basic usage after interacting with the page + it('Has no a11y violations after button click', () => { + // Interact with the page, then check for a11y issues + cy.contains('a', "What's next?").click(); + cy.checkA11y(null, undefined, terminalLogAxe); + }); + + it('Only logs a11y violations while allowing the test to pass', () => { + // Do not fail the test when there are accessibility failures + cy.checkA11y(null, undefined, terminalLogAxe, true); + }); + + it('Has no a11y violations after asynchronous load', () => { + // Retry the check if there are initial failures + cy.checkA11y( + null, + { + retries: 3, + interval: 100, + }, + terminalLogAxe + ); + }); +}); + +``` + +Using `cypress-axe` we first inject `axe-core` into the webpage within our _beforeEach_ hook, this ensures that each test in the spec file has been set up to run tests using the axe testing engine. + +```typescript +beforeEach(() => { + cy.visit('/'); + // highlight-next-line + cy.injectAxe(); +}); +``` + +Using the `cy.checkA11y()` function ([see docs for usage](https://github.com/component-driven/cypress-axe/blob/master/README.md)) we then test the webpage against various accessibility rules. + +```typescript +it('Has no detectable a11y violations on load (with custom parameters)', () => { + // Test the page at initial load (with context and options) + cy.checkA11y( + null, + { + // highlight-start + runOnly: { + type: 'tag', + values: ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'], + }, + // highlight-end + }, + terminalLogAxe + ); + +}); +``` + +Passing the `terminalLogAxe` function as a callback to `cy.checkA11y()` then creates and prints a readable table of accessibility violations to the console. (The `terminalLogAxe` function has been added to your _app-name/cypress/support/e2e.ts_ file) + +```typescript +it('Has no detectable a11y violations on load (with custom parameters)', () => { + // Test the page at initial load (with context and options) + cy.checkA11y( + null, + { + runOnly: { + type: 'tag', + values: ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'], + }, + }, + // highlight-next-line + terminalLogAxe + ); +}); +``` + +### Running your accessibility tests + +We recommend tagging your Cypress accessibility tests so that you can target these specific tests if required. In the below examples we have tagged the tests with **@accessibility** which enables us to target them through **grep** as seen in the ['Run specific tests'](./cypress_nx.md#run-specific-tests) example + + + + + ```typescript + //multiple tests grouped in a describe block + describe('Example test group @accessibility', () => { + + it('accessibility test 1', async ({ page }) => { + //test code + }); + + it('accessibility test 2', async ({ page }) => { + //test code + }); + } + ``` + + + + + ```typescript + it('Example individual test @accessibility', () => { + //Accessibility test with axe + }); + ``` + + + + +## Viewing your test results + +Further to the explanation given in the ['Testing with Cypress'](./cypress_nx.md#running-your-cypress-tests) page, accessibility test results can also be found in the console output post execution. + +```text title="Sample AXE report" +1) Has no detectable a11y violations on load (with custom parameters) +3 accessibility violations were detected +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β” +β”‚ (index) β”‚ id β”‚ impact β”‚ description β”‚ nodes β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ 0 β”‚ 'color-contrast' β”‚ 'serious' β”‚ 'Ensures the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds' β”‚ 1 β”‚ +β”‚ 1 β”‚ 'html-has-lang' β”‚ 'serious' β”‚ 'Ensures every HTML document has a lang attribute' β”‚ 1 β”‚ +β”‚ 2 β”‚ 'svg-img-alt' β”‚ 'serious' β”‚ 'Ensures elements with an img, graphics-document or graphics-symbol role have an accessible text' β”‚ 3 β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”˜ +``` diff --git a/docs/testing/testing_in_nx/cypress_nx.md b/docs/testing/testing_in_nx/cypress_nx.md new file mode 100644 index 000000000..ecda6bbd5 --- /dev/null +++ b/docs/testing/testing_in_nx/cypress_nx.md @@ -0,0 +1,248 @@ +--- +id: testing_with_cypress +title: Testing with Cypress +sidebar_label: Testing with cypress +description: Testing with cypress within an NX monorepo +keywords: + - NX + - testing + - cypress + - cross-browser +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +Cypress is a powerful testing framework that has gained popularity for its robust features and ease of use. Developed and maintained by a dedicated community, Cypress offers a comprehensive solution for web automation testing. It focuses on providing a seamless cross-browser experience, allowing developers to write reliable and efficient tests across different browsers. Due to it's popularity we are supporting it as a test framework within Ensono Stacks! + +## Getting Started + +Upon scaffolding your application with the Cypress testing framework, you will be presented with an example test suite and cypress configuration. The [`@nx/cypress`](https://www.npmjs.com/package/@nx/cypress) NX plugin is used as a base for the Cypress/NX integration. + +## Cypress Configuration + +### Base configuration + +The base configuration has been created with CI in mind, meaning the default configuration (shared across all projects) considers requirements for reporting and pipeline efficiency out of the box! This is created at the root of the project workspace and is used as the basis for each applications unique configuration. + +```typescript title="cypress.config.base.ts" +import { nxE2EPreset } from "@nx/cypress/plugins/cypress-preset"; + +const appName = process.env.NX_TASK_TARGET_PROJECT as string; +const outputFolderForProject = process.env.CI + ? `../../test-results/${appName}` + : "cypress/test-results"; +const baseURL = process.env.BASE_URL || "http://localhost:4200/"; +export const baseConfig: Cypress.ConfigOptions = { + // Test reporting configured with multiple reporters + reporter: "../../node_modules/cypress-multi-reporters", + // Spec: CI/Local (Default logging to console) + // mocha-junit-reporter: CI (JUnit XML reports for CI reporting) + // mochawesome: CI (Used for HTML report generation) + // Reports saved to asset folders to utilise automated 'trashAssets' mechanism + reporterOptions: { + reporterEnabled: !process.env.CI + ? "spec" + : "spec, mocha-junit-reporter, mochawesome", + mochaJunitReporterReporterOptions: { + mochaFile: outputFolderForProject.concat( + "/downloads/junit-report/results-[hash].xml" + ), + }, + // Mocha configuration for html reporting + mochawesomeReporterOptions: { + charts: true, + overwrite: false, + html: false, // set to false as will be generated during consolidation of json files + json: true, + reportDir: outputFolderForProject.concat("/downloads/reports-json-file"), + reportFilename: "[name].html", + embeddedScreenshots: true, + inlineAssets: true, + }, + }, + // Configuration for e2e tests + e2e: { + ...nxE2EPreset(__dirname, { cypressDir: "cypress" }), + baseUrl: baseURL, + // All assets directed into output folder + screenshotsFolder: outputFolderForProject.concat("/screenshots"), + videosFolder: outputFolderForProject.concat("/videos"), + downloadsFolder: outputFolderForProject.concat("/downloads"), + videoUploadOnPasses: false, + // Assets, including html reports, trashed before each run + trashAssetsBeforeRuns: true, + retries: { + runMode: process.env.CI ? 2 : 0, + }, + // Configure cypress grep + setupNodeEvents(on, config) { + require("@cypress/grep/src/plugin")(config); + return config; + }, + }, +}; +``` + +### Project based configuration + +Within the application where cypress has been added a cypress configuration file for that specific application will have been created. Extending the [base configuration](#base-configuration) this file can be used to add or change the default workspace configuration for cypress! +See the official [cypress docs](https://docs.cypress.io/guides/references/configuration) for more information on configuring your test project! + +```typescript title="cypress.config.ts" +import { defineConfig } from "cypress"; + +import { baseConfig } from "../../cypress.config.base"; + +export default defineConfig({ + ...baseConfig, + e2e: { + ...baseConfig.e2e, + screenshotOnRunFailure: true, + video: true, + }, +}); +``` + +## Testing + +### Writing tests + +When building your Cypress tests it helps to have a version of the application deployed for capturing locators and verifying your tests function as intended. + +You can serve your required application to localhost on port 4200 through the following command: + +```bash +nx serve +``` + +NX will then build and host your application, from here you can build/run your tests against a usable version of the application + +```log title="Example" +nx serve next-app + +> nx run next-app:serve:development + + info - automatically enabled Fast Refresh for 1 custom loader + event - compiled client and server successfully in 8.5s (166 modules) + [ ready ] on http://localhost:4200 +``` + +### Running your Cypress tests + +Using NX we can very easily run our tests, either for a specific project, or against any affected projects. NX will handle provisioning and tearing down of the web server automatically! +Using the NX β€˜affected’ capability allows you to run only the tests within a mono repo where the codebase has changes since the β€˜master’ commit. (See the [docs](https://nx.dev/concepts/affected) for more information) + + + + +```bash +nx e2e +``` + + + + +```bash +nx affected:e2e +``` + + + + +#### Run specific tests + +Looking at the following example, we have tagged the test with **@smoke-test** within the test case name + +```typescript +it("should be up and running @smoke-test", () => { + cy.get("#hero").find("span").should("have.text", "You're up and running"); +}); +``` + +We utilise [@cypress/grep](https://www.npmjs.com/package/@cypress/grep) to enable you to run this specific test. By specifying the grep parameter with the **@smoke-test** value alongside your run command, this specific test will be executed, similarly, if multiple tests contain **@smoke-test** within their name, they will also be executed. + +```bash +nx e2e --env.grep="@smoke-test" +``` + +## Testing Output + +### Viewing your test results + +Cypress has many configuration options for test reporting which can be found in [the documentation](https://docs.cypress.io/guides/tooling/reporters). + +#### Locally + +Using the scaffolded [base configuration](#base-configuration) all test results will be output to the terminal using cypress **_spec_** reporter, an example output can be seen below: + +```bash + Cypress example tests @example-cypress + - should take the user to the next steps part of the page when clicking whats next + √ App should be up and running @smoke + - App should have 5 learning materials @integration + 1 passing (1s) + 2 pending + (Results) + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Tests: 3 β”‚ + β”‚ Passing: 1 β”‚ + β”‚ Failing: 0 β”‚ + β”‚ Pending: 2 β”‚ + β”‚ Skipped: 0 β”‚ + β”‚ Screenshots: 0 β”‚ + β”‚ Video: false β”‚ + β”‚ Duration: 1 second β”‚ + β”‚ Spec Ran: example.cy.ts β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +==================================================================================================== + (Run Finished) + Spec Tests Passing Failing Pending Skipped + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ βœ” example.cy.ts 00:01 3 1 - 2 - β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + βœ” All specs passed! 00:01 3 1 - 2 - + + β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€” + + > NX Successfully ran target e2e for project next-cypress-application (29s) + + With additional flags: + --env={"grep":"@smoke"} +``` + +To change the reporter being used locally you can amend the [`cypress.config.ts`](#project-based-configuration) to overwrite the reporter definition in the [cypress.config.base.ts](#base-configuration), view the [Cypress documentation](https://docs.cypress.io/guides/tooling/reporters) for further information! + + \ No newline at end of file diff --git a/docs/testing/testing_in_nx/frontend_testing_in_nx.md b/docs/testing/testing_in_nx/frontend_testing_in_nx.md index 76bd6106f..7d4063465 100644 --- a/docs/testing/testing_in_nx/frontend_testing_in_nx.md +++ b/docs/testing/testing_in_nx/frontend_testing_in_nx.md @@ -7,6 +7,7 @@ keywords: - Nx - testing - playwright + - cypress - accessibility testing - visual regression testing - monorepo @@ -22,6 +23,8 @@ To leverage Ensono Stacks and accelerate your testing process within your Nx mon We recommend and currently support Playwright within the Ensono Stacks workflow, with it’s Microsoft backing, extensive feature set and fast cross-browser web automation capability, it is our preferred tooling choice. +However, existing users can still find information about the deprecated Cypress plugin [here](../../getting_started/cypress/plugin-information.md). + :::tip Visit the [`Playwright`](../../getting_started/playwright/plugin-information.md) Ensono Stacks plugin to start testing! diff --git a/docusaurus.config.js b/docusaurus.config.js index d474503bb..81112fca8 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -45,6 +45,7 @@ const config = { "Gatling", "Google Lighthouse", "Applitools", + "Cypress", "OWASP", ], docSearch: { diff --git a/sidebars.js b/sidebars.js index 6f0b7179c..f4a0746db 100644 --- a/sidebars.js +++ b/sidebars.js @@ -54,6 +54,7 @@ module.exports = { //"getting_started/azure-react/ensono-stacks-azure-react", Temporarily removed, add back in Cycle 11 "getting_started/rest-client/ensono-stacks-rest-client", "getting_started/playwright/ensono-stacks-playwright", + "getting_started/cypress/ensono-stacks-cypress", "getting_started/logger/ensono-stacks-logger", ], }, @@ -344,6 +345,14 @@ module.exports = { }, ], }, + { + type: "category", + label: "Cypress Information", + items: [ + "testing/testing_in_nx/testing_with_cypress", + "testing/testing_in_nx/cypress_accessibility_testing", + ], + }, ], }, "testing/testing_java_serenity_bdd",