From 95399919c020442fdbf656a4838f12ccf78ba6fc Mon Sep 17 00:00:00 2001 From: Nikita Barsukov Date: Thu, 28 Dec 2023 18:35:18 +0300 Subject: [PATCH] chore(demo-integrations): add Cypress Component Testing (#838) --- .github/workflows/e2e.yml | 14 ++++++++- nx.json | 8 ++++- package-lock.json | 12 +++---- projects/demo-integrations/cypress.config.ts | 9 +++++- projects/demo-integrations/project.json | 9 ++++++ .../src/support/commands/smart-tick.ts | 6 ++-- .../src/support/component-index.html | 18 +++++++++++ .../src/support/component.ts | 14 +++++++++ .../src/tests/component-testing/test.cy.ts | 31 +++++++++++++++++++ 9 files changed, 109 insertions(+), 12 deletions(-) create mode 100644 projects/demo-integrations/src/support/component-index.html create mode 100644 projects/demo-integrations/src/support/component.ts create mode 100644 projects/demo-integrations/src/tests/component-testing/test.cy.ts diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 44efee6fa..55900c09f 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -115,9 +115,21 @@ jobs: npm run cy:run -- --spec "**/(angular|react|ssr|addons|others)/**/*.cy.ts" --config baseUrl="${{ env.UNIVERSAL_SERVER }}" + component-testing: + if: ${{ !contains(github.head_ref, 'release/') }} + runs-on: ubuntu-latest + name: Component Testing + steps: + - uses: taiga-family/ci/actions/setup/checkout@v1.50.2 + - uses: taiga-family/ci/actions/setup/variables@v1.50.2 + - uses: taiga-family/ci/actions/setup/node@v1.50.2 + + - name: Run Cypress tests + run: npx nx component-test demo-integrations --browser=chrome + result: if: ${{ !contains(github.head_ref, 'release/') }} - needs: [build-demo, e2e-kit, e2e-recipes, e2e-others] + needs: [build-demo, e2e-kit, e2e-recipes, e2e-others, component-testing] runs-on: ubuntu-latest name: E2E result steps: diff --git a/nx.json b/nx.json index 6210bd3ed..b16b28a41 100644 --- a/nx.json +++ b/nx.json @@ -64,7 +64,9 @@ "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)", "!{projectRoot}/tsconfig.spec.json", "!{projectRoot}/jest.config.[jt]s", - "!{projectRoot}/src/test-setup.[jt]s" + "!{projectRoot}/src/test-setup.[jt]s", + "!{projectRoot}/**/*.cy.[jt]s?(x)", + "!{projectRoot}/cypress.config.[jt]s" ] }, "targetDefaults": { @@ -87,6 +89,10 @@ "codeCoverage": true } } + }, + "component-test": { + "cache": true, + "inputs": ["default", "^production"] } }, "parallel": 3 diff --git a/package-lock.json b/package-lock.json index 437a0d05c..7791f7c65 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18315,9 +18315,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001571", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001571.tgz", - "integrity": "sha512-tYq/6MoXhdezDLFZuCO/TKboTzuQ/xR5cFdgXPfDtM7/kchBO3b4VWghE/OAi/DV7tTdhmLjZiZBZi1fA/GheQ==", + "version": "1.0.30001572", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001572.tgz", + "integrity": "sha512-1Pbh5FLmn5y4+QhNyJE9j3/7dK44dGB83/ZMjv/qJk86TvDbjk0LosiZo0i0WB0Vx607qMX9jYrn1VLHCkN4rw==", "funding": [ { "type": "opencollective", @@ -44040,9 +44040,9 @@ } }, "node_modules/stylis": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.0.tgz", - "integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.1.tgz", + "integrity": "sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==", "optional": true }, "node_modules/stylus": { diff --git a/projects/demo-integrations/cypress.config.ts b/projects/demo-integrations/cypress.config.ts index d826b8790..acd0cb40b 100644 --- a/projects/demo-integrations/cypress.config.ts +++ b/projects/demo-integrations/cypress.config.ts @@ -1,3 +1,4 @@ +import {nxComponentTestingPreset} from '@nx/angular/plugins/component-testing'; import {nxE2EPreset} from '@nx/cypress/plugins/cypress-preset'; import {defineConfig} from 'cypress'; @@ -17,7 +18,13 @@ export const CYPRESS_CONFIG: Cypress.ConfigOptions = { return require('./src/plugins/index.js')(on, config); }, baseUrl: 'http://localhost:3333', - specPattern: 'src/tests/**/*.cy.ts', + specPattern: 'src/tests/!(component-testing)/**/*.cy.ts', + }, + component: { + ...nxComponentTestingPreset(__filename), + supportFile: 'src/support/component.ts', + indexHtmlFile: 'src/support/component-index.html', + specPattern: 'src/tests/component-testing/*.cy.ts', }, }; diff --git a/projects/demo-integrations/project.json b/projects/demo-integrations/project.json index 2a4866b2d..c8610bf13 100644 --- a/projects/demo-integrations/project.json +++ b/projects/demo-integrations/project.json @@ -11,6 +11,15 @@ "testingType": "e2e", "devServerTarget": "demo:serve:development" } + }, + "component-test": { + "executor": "@nx/cypress:cypress", + "options": { + "cypressConfig": "projects/demo-integrations/cypress.config.ts", + "testingType": "component", + "skipServe": true, + "devServerTarget": "demo:build" + } } }, "implicitDependencies": ["demo"] diff --git a/projects/demo-integrations/src/support/commands/smart-tick.ts b/projects/demo-integrations/src/support/commands/smart-tick.ts index b71184675..a5763724e 100644 --- a/projects/demo-integrations/src/support/commands/smart-tick.ts +++ b/projects/demo-integrations/src/support/commands/smart-tick.ts @@ -1,8 +1,8 @@ -export function smartTick( - $subject: Cypress.PrevSubjectMap[Cypress.PrevSubject], +export function smartTick[Cypress.PrevSubject]>( + $subject: T, durationMs: number, // ms frequencyMs = 100, // ms -): Cypress.Chainable { +): Cypress.Chainable { const iterations = Math.ceil(durationMs / frequencyMs); const lastIterationMs = durationMs % frequencyMs || frequencyMs; diff --git a/projects/demo-integrations/src/support/component-index.html b/projects/demo-integrations/src/support/component-index.html new file mode 100644 index 000000000..40a60a4c9 --- /dev/null +++ b/projects/demo-integrations/src/support/component-index.html @@ -0,0 +1,18 @@ + + + + + + + demo-integrations Components App + + +
+ + diff --git a/projects/demo-integrations/src/support/component.ts b/projects/demo-integrations/src/support/component.ts new file mode 100644 index 000000000..98467f017 --- /dev/null +++ b/projects/demo-integrations/src/support/component.ts @@ -0,0 +1,14 @@ +import './commands'; + +import {mount} from 'cypress/angular'; + +declare global { + namespace Cypress { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + interface Chainable { + mount: typeof mount; + } + } +} + +Cypress.Commands.add('mount', mount); diff --git a/projects/demo-integrations/src/tests/component-testing/test.cy.ts b/projects/demo-integrations/src/tests/component-testing/test.cy.ts new file mode 100644 index 000000000..f8ebe2c46 --- /dev/null +++ b/projects/demo-integrations/src/tests/component-testing/test.cy.ts @@ -0,0 +1,31 @@ +import {Component, Input} from '@angular/core'; +import {MaskitoDirective} from '@maskito/angular'; +import {MaskitoOptions} from '@maskito/core'; + +@Component({ + standalone: true, + imports: [MaskitoDirective], + template: ` + + `, +}) +class TestInput { + @Input() + maskitoOptions: MaskitoOptions | null = null; +} + +describe('Component testing demo', () => { + it('Test #1', () => { + const maskitoOptions: MaskitoOptions = {mask: /^\d+$/}; + + cy.mount(TestInput, {componentProperties: {maskitoOptions}}); + cy.get('input').type('123abc!!!!!567').should('have.value', '123567'); + }); + + it('Test #2', () => { + const maskitoOptions: MaskitoOptions = {mask: [/\d/, /\d/, ':', /\d/, /\d/]}; + + cy.mount(TestInput, {componentProperties: {maskitoOptions}}); + cy.get('input').type('1234').should('have.value', '12:34'); + }); +});