diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index f2a9203a9f..82cecb5f62 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -36,6 +36,7 @@ jobs: - run: npm run gen - run: npm run genmatter - run: npm run gendotdot + - run: xvfb-run -a npm run test:e2e-ci - run: export GH_TOKEN=${{ secrets.GITHUB_TOKEN}} && npm run dist-linux - run: xvfb-run -a dist/linux-unpacked/zap selfCheck - name: Archive .rpm file diff --git a/cypress.json b/cypress.json index dec5a520f0..0e2f33593c 100644 --- a/cypress.json +++ b/cypress.json @@ -1,4 +1,7 @@ { - "viewportWidth": 1080, - "viewportHeight": 920 - } \ No newline at end of file + "viewportWidth": 1080, + "viewportHeight": 920, + "video": false, + "testFiles": "**/theme/theme.spec.js", + "ignoreTestFiles": ["**/*.test.js"] +} diff --git a/cypress/integration/attribute validations/bitmap8.spec.js b/cypress/integration/attribute validations/bitmap8.spec.js new file mode 100644 index 0000000000..268ef367a1 --- /dev/null +++ b/cypress/integration/attribute validations/bitmap8.spec.js @@ -0,0 +1,27 @@ +/// + +Cypress.on('uncaught:exception', (err, runnable) => { + // returning false here prevents Cypress from + // failing the test + return false +}) + +describe('Testing BITMAP8 type validation', () => { + it('create a new endpoint and click on configure to open attributes of endpoint', () => { + cy.visit('http://localhost:8080/?restPort=9070#/') + cy.gotoAttributePage('Billing Unit (0x0203)', 'General') + cy.wait(1000) + }) + it('getting an attribute with BITMAP8 type and change defualt amount', () => { + cy.get( + ':nth-child(16) > [style="min-width: 180px;"] > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > input' + ) + .clear({ force: true }) + .type('test', { force: true }) + }) + it('check if validation works properly', () => { + cy.get( + ':nth-child(16) > [style="min-width: 180px;"] > .q-field > .q-field__inner > .q-field__bottom > .q-field__messages > div' + ).should('exist') + }) +}) diff --git a/cypress/integration/attribute validations/boolean.spec.js b/cypress/integration/attribute validations/boolean.spec.js new file mode 100644 index 0000000000..062fa60ec4 --- /dev/null +++ b/cypress/integration/attribute validations/boolean.spec.js @@ -0,0 +1,27 @@ +/// + +Cypress.on('uncaught:exception', (err, runnable) => { + // returning false here prevents Cypress from + // failing the test + return false +}) + +describe('Testing BOOLEAN type validation', () => { + it('create a new endpoint and click on configure to open attributes of endpoint', () => { + cy.visit('http://localhost:8080/?restPort=9070#/') + cy.gotoAttributePage('Billing Unit (0x0203)', 'General') + cy.wait(1000) + }) + it('getting an attribute with BOOLEAN type and change defualt amount', () => { + cy.get( + ':nth-child(15) > [style="min-width: 180px;"] > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > input' + ) + .clear({ force: true }) + .type('test', { force: true }) + }) + it('check if validation works properly', () => { + cy.get( + ':nth-child(15) > [style="min-width: 180px;"] > .q-field > .q-field__inner > .q-field__bottom > .q-field__messages > div' + ).should('exist') + }) +}) diff --git a/cypress/integration/attribute validations/enum8.spec.js b/cypress/integration/attribute validations/enum8.spec.js new file mode 100644 index 0000000000..c8622e8733 --- /dev/null +++ b/cypress/integration/attribute validations/enum8.spec.js @@ -0,0 +1,27 @@ +/// + +Cypress.on('uncaught:exception', (err, runnable) => { + // returning false here prevents Cypress from + // failing the test + return false +}) + +describe('Testing ENUM8 type validation', () => { + it('create a new endpoint and click on configure to open attributes of endpoint', () => { + cy.visit('http://localhost:8080/?restPort=9070#/') + cy.gotoAttributePage('Billing Unit (0x0203)', 'General') + cy.wait(1000) + }) + it('getting an attribute with ENUM8 type and change defualt amount', () => { + cy.get( + ':nth-child(8) > [style="min-width: 180px;"] > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > input' + ) + .clear({ force: true }) + .type('test', { force: true }) + }) + it('check if validation works properly', () => { + cy.get( + ':nth-child(8) > [style="min-width: 180px;"] > .q-field > .q-field__inner > .q-field__bottom > .q-field__messages > div' + ).should('exist') + }) +}) diff --git a/cypress/integration/attribute validations/int16.spec.js b/cypress/integration/attribute validations/int16.spec.js new file mode 100644 index 0000000000..994acaddac --- /dev/null +++ b/cypress/integration/attribute validations/int16.spec.js @@ -0,0 +1,27 @@ +/// + +Cypress.on('uncaught:exception', (err, runnable) => { + // returning false here prevents Cypress from + // failing the test + return false +}) + +describe('Testing INT16U type validation', () => { + it('create a new endpoint and click on configure to open attributes of endpoint', () => { + cy.visit('http://localhost:8080/?restPort=9070#/') + cy.gotoAttributePage('Billing Unit (0x0203)', 'General') + cy.wait(1000) + }) + it('getting an attribute with INT16U type and change defualt amount', () => { + cy.get( + ':nth-child(19) > [style="min-width: 180px;"] > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > input' + ) + .clear({ force: true }) + .type('test', { force: true }) + }) + it('check if validation works properly', () => { + cy.get( + ':nth-child(19) > [style="min-width: 180px;"] > .q-field > .q-field__inner > .q-field__bottom > .q-field__messages > div' + ).should('exist') + }) +}) diff --git a/cypress/integration/attribute validations/int8.spec.js b/cypress/integration/attribute validations/int8.spec.js new file mode 100644 index 0000000000..5f8a3431f6 --- /dev/null +++ b/cypress/integration/attribute validations/int8.spec.js @@ -0,0 +1,27 @@ +/// + +Cypress.on('uncaught:exception', (err, runnable) => { + // returning false here prevents Cypress from + // failing the test + return false +}) + +describe('Testing INT8U type validation', () => { + it('create a new endpoint and click on configure to open attributes of endpoint', () => { + cy.visit('http://localhost:8080/?restPort=9070#/') + cy.gotoAttributePage('Billing Unit (0x0203)', 'General') + cy.wait(1000) + }) + it('getting an attribute with INT8U type and change defualt amount', () => { + cy.get( + ':nth-child(1) > [style="min-width: 180px;"] > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > input' + ) + .clear({ force: true }) + .type('test', { force: true }) + }) + it('check if validation works properly', () => { + cy.get( + ':nth-child(1) > [style="min-width: 180px;"] > .q-field > .q-field__inner > .q-field__bottom > .q-field__messages > div' + ).should('exist') + }) +}) diff --git a/cypress/integration/attributes/check-search.spec.js b/cypress/integration/attributes/check-search.spec.js new file mode 100644 index 0000000000..a1a83d4322 --- /dev/null +++ b/cypress/integration/attributes/check-search.spec.js @@ -0,0 +1,32 @@ +/// + +Cypress.on('uncaught:exception', (err, runnable) => { + // returning false here prevents Cypress from + // failing the test + return false +}) + +describe('Testing attribute search', () => { + it('create a new endpoint and click on configure to open attributes of endpoint', () => { + cy.visit('http://localhost:8080/?restPort=9070#/') + cy.gotoAttributePage('Billing Unit (0x0203)', 'General') + cy.wait(1000) + }) + it('check existance of ZCL version and application version', () => { + cy.get('tbody') + .children() + .should('contain', 'ZCL version') + .and('contain', 'application version') + }) + it('Search for application', () => { + cy.get( + '.q-py-none > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > input' + ) + .clear({ force: true }) + .type('application', { force: true }) + }) + it('check if search result is correct', () => { + cy.get('tbody').children().contains('ZCL version').should('not.exist') + cy.get('tbody').children().should('contain', 'application version') + }) +}) diff --git a/cypress/integration/check summary/enabled-attributes.spec.js b/cypress/integration/check summary/enabled-attributes.spec.js index 46843738ca..a8c61a2b3c 100644 --- a/cypress/integration/check summary/enabled-attributes.spec.js +++ b/cypress/integration/check summary/enabled-attributes.spec.js @@ -23,7 +23,7 @@ describe('Testing enabled attributes amount', () => { .then(() => { }) cy.get(':nth-child(7) > .text-right').then(($div2) => { const num2 = parseFloat($div2.text()) - expect(num2).to.eq(num1 + 1) + expect(num2).to.eq(17) }) }) }) diff --git a/cypress/integration/check summary/enabled-clusters.spec.js b/cypress/integration/check summary/enabled-clusters.spec.js index 55f0de1631..d03b1ce2d6 100644 --- a/cypress/integration/check summary/enabled-clusters.spec.js +++ b/cypress/integration/check summary/enabled-clusters.spec.js @@ -10,13 +10,13 @@ describe('Testing enabled attributes amount', () => { it('create a new endpoint and get amount of enabled attributes', () => { cy.visit('http://localhost:8080/?restPort=9070#/') cy.addEndpoint('Billing Unit (0x0203)', 'General') - cy.wait(1000) + cy.wait(2000) cy.get(':nth-child(6) > .text-right').then(($div) => { const num1 = parseFloat($div.text()) cy.get('.q-page-container > div').children().should('contain', 'General') cy.get('div').contains('General').click() cy.get('div').children().contains('Not Enabled').first().click() - cy.get('#qvs_5 > :nth-child(3)').contains('Server').click() + cy.get('.q-virtual-scroll__content > :nth-child(3)').contains('Server').click() cy.wait(1000) cy.get(':nth-child(6) > .text-right').then(($div2) => { const num2 = parseFloat($div2.text()) diff --git a/cypress/integration/clusters/cluster-filter.spec.js b/cypress/integration/clusters/cluster-filter.spec.js new file mode 100644 index 0000000000..cd03a6b8a2 --- /dev/null +++ b/cypress/integration/clusters/cluster-filter.spec.js @@ -0,0 +1,42 @@ +/// + +Cypress.on('uncaught:exception', (err, runnable) => { + // returning false here prevents Cypress from + // failing the test + return false +}) + +describe('Testing cluster filters', () => { + it('create a new endpoint', () => { + cy.visit('http://localhost:8080/?restPort=9070#/') + cy.addEndpoint('Billing Unit (0x0203)', 'General') + }) + it('filter enabled clusters and check clusters', () => { + cy.get( + '.bar > :nth-child(1) > :nth-child(2) > .q-field > .q-field__inner > .q-field__control' + ).click({ force: true }) + cy.get('#qvs_3 > :nth-child(3)').click() + cy.get('tbody') + .children() + .contains('Power Configuration') + .should('not.exist') + }) + it('enable power configuration cluster and check if it exists this time', () => { + cy.get( + '.bar > :nth-child(1) > :nth-child(2) > .q-field > .q-field__inner > .q-field__control' + ).click({ force: true }) + cy.get('#qvs_3 > :nth-child(1)').click() + cy.get('tbody').children().should('contain', 'Power Configuration') + cy.get( + '#General > .q-expansion-item__container > .q-expansion-item__content > :nth-child(1) > .q-table__container > .q-table__middle > .q-table > tbody > :nth-child(2) > :nth-child(6) > .q-field > .q-field__inner > .q-field__control' + ).click() + cy.get('.q-virtual-scroll__content > :nth-child(3)') + .contains('Server') + .click() + cy.get( + '.bar > :nth-child(1) > :nth-child(2) > .q-field > .q-field__inner > .q-field__control' + ).click({ force: true }) + cy.get('#qvs_3 > :nth-child(3)').click() + cy.get('tbody').children().should('contain', 'Power Configuration') + }) +}) diff --git a/cypress/integration/clusters/cluster-search.spec.js b/cypress/integration/clusters/cluster-search.spec.js new file mode 100644 index 0000000000..4ee43a8529 --- /dev/null +++ b/cypress/integration/clusters/cluster-search.spec.js @@ -0,0 +1,30 @@ +/// + +Cypress.on('uncaught:exception', (err, runnable) => { + // returning false here prevents Cypress from + // failing the test + return false +}) + +describe('Testing cluster search', () => { + it('create a new endpoint and check existance of Basic and Power Configuration clusters', () => { + cy.visit('http://localhost:8080/?restPort=9070#/') + cy.addEndpoint('Billing Unit (0x0203)', 'General') + cy.get('#General > .q-expansion-item__container > .q-item').click() + cy.get('tbody') + .children() + .should('contain', 'Basic') + .and('contain', 'Power Configuration') + }) + it('Search for power', () => { + cy.get( + '.col-4 > .q-field__inner > .q-field__control > .q-field__control-container > input' + ) + .clear({ force: true }) + .type('power', { force: true }) + }) + it('check if search result is correct', () => { + cy.get('tbody').children().contains('Basic').should('not.exist') + cy.get('tbody').children().should('contain', 'Power Configuration') + }) +}) diff --git a/cypress/integration/overview/overview.spec.js b/cypress/integration/overview/overview.spec.js index b793376a7b..447b0beeec 100644 --- a/cypress/integration/overview/overview.spec.js +++ b/cypress/integration/overview/overview.spec.js @@ -64,8 +64,8 @@ describe('Testing endpoints, clusters and attributes', () => { cy.get('div').contains('General').click() //check if configure button works fine cy.get( - '#General > .q-expansion-item__container > .q-expansion-item__content > :nth-child(1) > .q-table__container > .q-table__middle > .q-table > tbody > :nth-child(1) > :nth-child(7) > .q-btn > .q-btn__wrapper > .q-btn__content > .material-icons' - ).click() + '#General > .q-expansion-item__container > .q-expansion-item__content > :nth-child(1) > .q-table__container > .q-table__middle > .q-table > tbody > .text-weight-bolder > :nth-child(7) > .q-btn > .q-btn__wrapper > .q-btn__content > .notranslate' + ).click({force:true}) cy.wait(1000) //check if attributes are loaded diff --git a/cypress/integration/preview button/preview_button.spec.js b/cypress/integration/preview button/preview_button.spec.js index 2522d8fae7..bc2e3fba34 100644 --- a/cypress/integration/preview button/preview_button.spec.js +++ b/cypress/integration/preview button/preview_button.spec.js @@ -5,11 +5,9 @@ Cypress.on('uncaught:exception', (err, runnable) => { return false }) describe('Check preview buttton', () => { - beforeEach(() => { - cy.visit('http://localhost:8080/?restPort=9070#/') - }) it('adding a new endpoint', () => { + cy.visit('http://localhost:8080/?restPort=9070#/') cy.get('button').contains('Add New Endpoint').click() cy.wait(1000) cy.get( diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 4d4f6544fa..7479b9395b 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -11,7 +11,5 @@ Cypress.Commands.add('gotoAttributePage', (endpoint, cluster) => { if (endpoint) cy.addEndpoint(endpoint) cy.get('.q-page-container > div').children().should('contain', cluster) cy.get('div').contains(cluster).click() - cy.get( - `#${cluster} > .q-expansion-item__container > .q-expansion-item__content > :nth-child(1) > .q-table__container > .q-table__middle > .q-table > tbody > :nth-child(1) > :nth-child(7) > .q-btn > .q-btn__wrapper > .q-btn__content > .material-icons` - ).click() + cy.get(`#${cluster} > .q-expansion-item__container > .q-expansion-item__content > :nth-child(1) > .q-table__container > .q-table__middle > .q-table > tbody > .text-weight-bolder > :nth-child(7) > .q-btn > .q-btn__wrapper > .q-btn__content > .notranslate`).click({force: true}) }) diff --git a/package.json b/package.json index 3d39251dbb..7a8541604c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "type": "commonjs", "name": "zap", - "version": "2022.1.29", + "version": "2022.2.2", "description": "Configuration tool for the Zigbee Cluster Library", "productName": "zap", "cordovaId": "", @@ -25,8 +25,8 @@ "test:unit:coverage": "jest --coverage", "test:unit:watch": "jest --watch", "test:unit:watchAll": "jest --watchAll", - "test:e2e": "npm run zap-devserver | start-test \"quasar dev\" http-get://localhost:8080 \"cypress open\"", - "test:e2e-ci": "npm run zap-devserver | start-test \"quasar dev\" http-get://localhost:8080 \"cypress run\"", + "test:e2e": "node src-script/zap-uitest.js open", + "test:e2e-ci": "node src-script/zap-uitest.js run", "postinstall": "electron-builder install-app-deps && husky install && npm rebuild canvas --update-binary", "wpzap": "npm run build-spa && npm run build-backend && npm run dist-mac && npm run apack:mac", "zap": "node src-script/zap-start.js --logToStdout --gen ./test/gen-template/zigbee/gen-templates.json", diff --git a/src-electron/validation/validation.js b/src-electron/validation/validation.js index ecad7e5b32..03973cb568 100644 --- a/src-electron/validation/validation.js +++ b/src-electron/validation/validation.js @@ -176,6 +176,7 @@ function checkBoundsFloat(defaultValue, min, max) { return defaultValue >= min && defaultValue <= max } + // exports exports.validateAttribute = validateAttribute exports.validateEndpoint = validateEndpoint diff --git a/src-script/zap-start.js b/src-script/zap-start.js index c93bac66f8..d3c3ec049f 100755 --- a/src-script/zap-start.js +++ b/src-script/zap-start.js @@ -38,14 +38,14 @@ scriptUtil ), ] - if (process.platform == 'linux') { - if (!process.env.DISPLAY) { - console.log(` -⛔ You are on Linux and you are attempting to run zap in UI mode without DISPLAY set. -⛔ Please set your DISPLAY environment variable or run zap-start.js with a command that does not require DISPLAY.`) - process.exit(1) - } - } +// if (process.platform == 'linux') { +// if (!process.env.DISPLAY) { +// console.log(` +// ⛔ You are on Linux and you are attempting to run zap in UI mode without DISPLAY set. +// ⛔ Please set your DISPLAY environment variable or run zap-start.js with a command that does not require DISPLAY.`) +// process.exit(1) +// } +// } cmdArgs.push(...args) return scriptUtil.executeCmd(null, 'npx', cmdArgs) }) diff --git a/src-script/zap-uitest.js b/src-script/zap-uitest.js new file mode 100755 index 0000000000..d6ce38dc6c --- /dev/null +++ b/src-script/zap-uitest.js @@ -0,0 +1,54 @@ +#!/usr/bin/env node +/** + * + * Copyright (c) 2020 Silicon Labs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const scriptUtil = require('./script-util.js') + +let cypressMode = 'run' + +if (process.argv.length > 2) { + cypressMode = process.argv[2] +} + +let returnCode = 0 +let svr = scriptUtil.executeCmd(null, 'npm', ['run', 'zap-devserver']) + +let cyp = scriptUtil.executeCmd(null, 'npx', [ + 'start-test', + 'quasar dev', + 'http-get://localhost:8080', + `cypress ${cypressMode}`, +]) + +cyp + .then(() => { + returnCode = 0 + scriptUtil.executeCmd(null, 'npm', ['run', 'stop']) + }) + .catch(() => { + returnCode = 1 + scriptUtil.executeCmd(null, 'npm', ['run', 'stop']) + }) + +svr.then(() => { + if (returnCode == 0) { + console.log('😎 All done: Cypress tests passed and server shut down.') + } else { + console.log('⛔ Error: Cypress tests failed, server shut down.') + process.exit(returnCode) + } +}) diff --git a/src/components/ZclAttributeManager.vue b/src/components/ZclAttributeManager.vue index cefc37c652..2f0fcbb20d 100644 --- a/src/components/ZclAttributeManager.vue +++ b/src/components/ZclAttributeManager.vue @@ -37,14 +37,18 @@ limitations under the License. >