From e5937e136e13ed0287fb427a889224591a689d74 Mon Sep 17 00:00:00 2001 From: maipt Date: Tue, 12 Nov 2024 11:48:52 +0700 Subject: [PATCH] feat(Cypress): Add selectors into selectors.js files --- cypress/e2e/components/delete.cy.js | 17 +- .../e2e/components/export-spreadsheet.cy.js | 10 +- cypress/e2e/components/import.cy.js | 24 +-- cypress/e2e/components/register.cy.js | 20 +- cypress/e2e/components/selectors.js | 93 +++++++++ cypress/e2e/components/utils.js | 89 ++++----- cypress/e2e/releases/link-to-project.cy.js | 15 +- cypress/e2e/releases/selectors.js | 139 +++++++++++++ cypress/e2e/releases/utils.js | 182 +++++++----------- cypress/fixtures/releases/register.json | 2 +- 10 files changed, 379 insertions(+), 212 deletions(-) create mode 100644 cypress/e2e/components/selectors.js create mode 100644 cypress/e2e/releases/selectors.js diff --git a/cypress/e2e/components/delete.cy.js b/cypress/e2e/components/delete.cy.js index bcf511ff0..492fb3c30 100644 --- a/cypress/e2e/components/delete.cy.js +++ b/cypress/e2e/components/delete.cy.js @@ -1,26 +1,27 @@ import { gotoViewComponentPage, createComponent, createRelease } from './utils.js'; +import { viewSelectors } from './selectors' function deleteComponent(componentName) { // go to component page cy.visit(`${Cypress.env('sw360_base_url')}/components`) cy.contains('Add Component') cy.get('a:contains(' + componentName + ')').closest('tr').find('td').last().find('svg').last().click() - cy.get('.modal-content').should('be.visible') - cy.get('.login-btn').click() + cy.get(viewSelectors.dialogDeleteComponent.dialog).should('be.visible') + cy.get(viewSelectors.dialogDeleteComponent.btnDeleteComponent).click() verifyDeleteSuccessfully() } function verifyDeleteSuccessfully() { - cy.get('.alert-success').should('be.visible') - cy.get('.delete-btn').click() + cy.get(viewSelectors.dialogDeleteComponent.alertSuccess).should('be.visible') + cy.get(viewSelectors.dialogDeleteComponent.btnClose).click() } function deleteAllReleaseOfComponent(numberOfReleases) { for (let i = 0; i < numberOfReleases; i++) { - cy.get('#tab-Releases').click() - cy.get('[data-column-id="action"] > div > span').should('have.length', numberOfReleases - i) - cy.get('[data-column-id="action"] > div > span').first().find('svg').last().click() - cy.get('.login-btn').click() + cy.get(viewSelectors.tabReleaseOverview).click() + cy.get(viewSelectors.actionsInReleaseListTbl).should('have.length', numberOfReleases - i) + cy.get(viewSelectors.actionsInReleaseListTbl).first().find('svg').last().click() + cy.get(viewSelectors.btnDeleteRelease).click() verifyDeleteSuccessfully() } } diff --git a/cypress/e2e/components/export-spreadsheet.cy.js b/cypress/e2e/components/export-spreadsheet.cy.js index c677755f5..83591fcca 100644 --- a/cypress/e2e/components/export-spreadsheet.cy.js +++ b/cypress/e2e/components/export-spreadsheet.cy.js @@ -8,6 +8,8 @@ // SPDX-License-Identifier: EPL-2.0 // License-Filename: LICENSE +import { viewSelectors } from './selectors' + const verifyFileExported = () => { const currentDate = new Date().toISOString().split("T")[0] cy.readFile(`cypress/downloads/components-${currentDate}.xlsx`) @@ -21,15 +23,15 @@ describe('Export Spreadsheet', () => { }) it('TC13: Export components without releases', () => { - cy.get('#project-export').click() - cy.get('.dropdown-menu > :nth-child(1)').click() + cy.get(viewSelectors.btnExportSpreadsheet).click() + cy.get(viewSelectors.btnExportComponentsOnly).click() verifyFileExported() cy.removeDownloadedFiles() }) it('TC14: Export components with releases', () => { - cy.get('#project-export').click() - cy.get('.dropdown-menu > :nth-child(2)').click() + cy.get(viewSelectors.btnExportSpreadsheet).click() + cy.get(viewSelectors.btnExportComponentsWithReleases).click() verifyFileExported() cy.removeDownloadedFiles() }) diff --git a/cypress/e2e/components/import.cy.js b/cypress/e2e/components/import.cy.js index b5b19ad52..59cb2d022 100644 --- a/cypress/e2e/components/import.cy.js +++ b/cypress/e2e/components/import.cy.js @@ -8,10 +8,12 @@ // SPDX-License-Identifier: EPL-2.0 // License-Filename: LICENSE +import { viewSelectors } from './selectors' + const verifyModalData = (testData) => { - cy.get('.modal-body > div > p').contains('The new Component and new Release will be created, do you want to import?') - cy.get('.modal-body > div > div:nth-child(2)').contains(`New Components: ${testData.component}`) - cy.get('.modal-body > div > div:nth-child(3)').contains(`New Releases: ${testData.release.name}`) + cy.get(viewSelectors.dialogUploadSBOM.message1).contains('The new Component and new Release will be created, do you want to import?') + cy.get(viewSelectors.dialogUploadSBOM.message2).contains(`New Components: ${testData.component}`) + cy.get(viewSelectors.dialogUploadSBOM.message3).contains(`New Releases: ${testData.release.name}`) } const verifyImportSuccess = (testData) => { @@ -20,24 +22,24 @@ const verifyImportSuccess = (testData) => { } const verifyComponent = (component) => { - cy.get('.text-truncate').contains(component, { matchCase: false }) + cy.get(viewSelectors.componentName).contains(component, { matchCase: false }) } const verifyRelease = (release) => { - cy.get('#tab-Releases').click() - cy.get(':nth-child(3) > .row > :nth-child(2) .gridjs-table > tbody > tr > td:nth-child(1)').contains(release.name) - cy.get(':nth-child(3) > .row > :nth-child(2) .gridjs-table > tbody > tr > td:nth-child(2)').contains(release.version) + cy.get(viewSelectors.tabReleaseOverview).click() + cy.get(viewSelectors.tblReleasesList.releaseName).contains(release.name) + cy.get(viewSelectors.tblReleasesList.releaseVersion).contains(release.version) } const selectFile = (filePath) => { - cy.get('input[type="file"]').selectFile(filePath, {force: true}) + cy.get(viewSelectors.uploadFiles).selectFile(filePath, {force: true}) } const importSPDX = (testId) => { cy.fixture('components/import-spdx').then((data) => { const testData = data[testId] selectFile(testData.filePath) - const importButton = cy.get('.modal-content .btn-primary').contains('Import') + const importButton = cy.get(viewSelectors.dialogUploadSBOM.btnImportAndClose).contains('Import') verifyModalData(testData) importButton.click() verifyImportSuccess(testData) @@ -52,12 +54,12 @@ describe('TC12: Import a new component by .spdx/.xml/ .rdf file', () => { }) it.skip('Import SPDX in .rdf format', () => { - cy.get('a>.btn-secondary').click() + cy.get(viewSelectors.btnImportSBOM).click() importSPDX('IMPORT_SPDX_001') }) it('Import SPDX in .spdx format', () => { - cy.get('a>.btn-secondary').click() + cy.get(viewSelectors.btnImportSBOM).click() importSPDX('IMPORT_SPDX_002') }) diff --git a/cypress/e2e/components/register.cy.js b/cypress/e2e/components/register.cy.js index ace0b10e5..06852c93c 100644 --- a/cypress/e2e/components/register.cy.js +++ b/cypress/e2e/components/register.cy.js @@ -9,11 +9,12 @@ // License-Filename: LICENSE import { registerComponent } from './utils.js'; -import { updateRelease, registerAndVerifyRelease, updateAndVerifyReleaseAfterUpdate, gotoUpdateReleasePageFromViewReleasePage } from '../releases/utils.js'; +import { registerAndVerifyRelease, updateAndVerifyReleaseAfterUpdate, gotoUpdateReleasePageFromViewReleasePage } from '../releases/utils.js'; +import { addEditSelectors } from './selectors' function verifyComponentAfterCreated(testId) { cy.log('[Info] Validate Testcase') - cy.get('.btn-group > :nth-child(1) > .btn') + cy.get(addEditSelectors.btnUpdateComponent) .contains('Update Component') cy.fixture('components/register').then((component) => { const dataTest = component[testId] @@ -30,19 +31,19 @@ function verifyComponentAfterCreated(testId) { case 'description': case 'owner_accounting_unit': case 'owner_billing_group': - cy.get('#' + keyFieldName) + cy.get(addEditSelectors.fillData(keyFieldName)) .should('have.value', fieldValue) break case 'component_type': case 'country': - cy.get('#' + keyFieldName) + cy.get(addEditSelectors.fillData(keyFieldName)) .should('have.value', fieldValue.value) break case 'default_vendor': // break case 'homeurl': - cy.get('#tag') + cy.get(addEditSelectors.txtHomeUrl) .should('have.value', dataTest.homeurl) break case 'component_owner': @@ -54,15 +55,15 @@ function verifyComponentAfterCreated(testId) { case 'additional_roles': break case 'external_id': - cy.get(':nth-child(4) > :nth-child(2) > .row > .col-lg-6 > .form-control') + cy.get(addEditSelectors.addRowExternalId.key) .should('have.value', fieldValue.key) - cy.get(':nth-child(4) > :nth-child(2) > .row > .col-lg-5 > .form-control') + cy.get(addEditSelectors.addRowExternalId.value) .should('have.value', fieldValue.value) break case 'additional_data': - cy.get(':nth-child(5) > :nth-child(2) > .row > .col-lg-6 > .form-control') + cy.get(addEditSelectors.addRowAdditionalData.key) .should('have.value', fieldValue.key) - cy.get(':nth-child(5) > :nth-child(2) > .row > .col-lg-5 > .form-control') + cy.get(addEditSelectors.addRowAdditionalData.value) .should('have.value', fieldValue.value) break default: @@ -70,7 +71,6 @@ function verifyComponentAfterCreated(testId) { } } }) - } export function registerAndVerifyComponent(testId) { diff --git a/cypress/e2e/components/selectors.js b/cypress/e2e/components/selectors.js new file mode 100644 index 000000000..b40d81ccc --- /dev/null +++ b/cypress/e2e/components/selectors.js @@ -0,0 +1,93 @@ +// Copyright (C) TOSHIBA CORPORATION, 2024. Part of the SW360 Frontend Project. +// Copyright (C) Toshiba Software Development (Vietnam) Co., Ltd., 2024. Part of the SW360 Frontend Project. + +// This program and the accompanying materials are made +// available under the terms of the Eclipse Public License 2.0 +// which is available at https://www.eclipse.org/legal/epl-2.0/ + +// SPDX-License-Identifier: EPL-2.0 +// License-Filename: LICENSE + +// elements of add/edit component page +export const addEditSelectors = { + btnCreateComponent: '.btn-toolbar button[type="submit"]', + btnUpdateComponent: '.btn-group > :nth-child(1) > .btn', + fillData: (key) => `#${key}`, + txtHomeUrl: '#tag', + btnDeleteAllModerators: ':nth-child(2) > :nth-child(3) > :nth-child(2) > span', + dialogVendor: { + "openDialog": "#default_vendor", + "dialog": ".modal.show > .modal-dialog > .modal-content", + "addVendorBtn": ".justify-content-end > :nth-child(2)", + "addVendorBtnInAddVendorDialog": "", + "searchBtn": ":nth-child(2) > .modal-body > :nth-child(1) > .col-lg-4 > :nth-child(1)", + "selectUser": "[data-column-id=\"vendorId\"] > :nth-child(1) > div > .form-check-input", + "selectVendorBtn": ".justify-content-end > :nth-child(3)" + }, + + dialogOwner: { + "openDialog": "#component_owner", + "dialog": ".modal.show > .modal-dialog > .modal-content", + "searchBtn": ".modal.show > .modal-dialog > .modal-content > .modal-body > :nth-child(1) > .col-lg-4 > :nth-child(1)", + "selectUser": "[data-column-id=\"user-selection\"] .form-check-input", + "selectUsersBtn": ".justify-content-end > .btn-primary" + }, + + dialogModerator: { + "openDialog": "#moderators", + "dialog": ".modal.show > .modal-dialog > .modal-content", + "searchBtn": ".modal.show > .modal-dialog > .modal-content > .modal-body > :nth-child(1) > .col-lg-4 > :nth-child(1)", + "selectUser": "[data-column-id=\"user-selection\"] .form-check-input", + "selectUsersBtn": ".justify-content-end > .btn-primary" + }, + + addRowExternalId: { + 'btnAddRow': ':nth-child(4) > .row > .col-lg-4 > .btn', + 'key': '.form-control[aria-describedby="external id key"]', + 'value': '.form-control[aria-describedby="external id value"]' + }, + + addRowAdditionalData: { + 'btnAddRow': ':nth-child(5) > .row > .col-lg-4 > .btn', + 'key': '.form-control[aria-describedby="additional data key"]', + 'value': '.form-control[aria-describedby="additional data value"]' + } +} + +//elements of view page +export const viewSelectors = { + navComponents: '[href="/components"]', + tblComponentList: '[style="margin-bottom: 20px;"] > .col', + hyperlinkComponentNames: '[data-column-id="name"] > div > .link', + tabReleaseOverview: '#tab-Releases', + tblReleasesList: { + table: ':nth-child(3) > .row > :nth-child(2) > .gridjs', + releaseName: ':nth-child(3) > .row > :nth-child(2) .gridjs-table > tbody > tr > td:nth-child(1)', + releaseVersion: ':nth-child(3) > .row > :nth-child(2) .gridjs-table > tbody > tr > td:nth-child(2)' + }, + dialogDeleteComponent: { + dialog: '.modal-content', + btnDeleteComponent: '.login-btn', + alertSuccess: '.alert-success', + btnClose: '.delete-btn' + }, + + btnExportSpreadsheet: '#project-export', + btnExportComponentsOnly: '.dropdown-menu > :nth-child(1)', + btnExportComponentsWithReleases: '.dropdown-menu > :nth-child(2)', + btnImportSBOM: 'a>.btn-secondary', + uploadFiles: 'input[type="file"]', + dialogUploadSBOM: { + message1: '.modal-body > div > p', + message2: '.modal-body > div > div:nth-child(2)', + message3: '.modal-body > div > div:nth-child(3)', + btnImportAndClose: '.modal-content .btn-primary' + + }, + + componentName: '.text-truncate', + + // Release Overview tab + actionsInReleaseListTbl: '[data-column-id="action"] > div > span', + btnDeleteRelease: '.login-btn' +} \ No newline at end of file diff --git a/cypress/e2e/components/utils.js b/cypress/e2e/components/utils.js index 693044176..409fbfcd7 100644 --- a/cypress/e2e/components/utils.js +++ b/cypress/e2e/components/utils.js @@ -8,35 +8,11 @@ // SPDX-License-Identifier: EPL-2.0 // License-Filename: LICENSE -const dialogVendor = { - "openDialog": "#default_vendor", - "dialog": ".modal.show > .modal-dialog > .modal-content", - "addVendorBtn": ".justify-content-end > :nth-child(2)", - "addVendorBtnInAddVendorDialog": "", - "searchBtn": ":nth-child(2) > .modal-body > :nth-child(1) > .col-lg-4 > :nth-child(1)", - "selectUser": "[data-column-id=\"vendorId\"] > :nth-child(1) > div > .form-check-input", - "selectVendorBtn": ".justify-content-end > :nth-child(3)" -} - -const dialogOwner = { - "openDialog": "#component_owner", - "dialog": ".modal.show > .modal-dialog > .modal-content", - "searchBtn": ".modal.show > .modal-dialog > .modal-content > .modal-body > :nth-child(1) > .col-lg-4 > :nth-child(1)", - "selectUser": "[data-column-id=\"user-selection\"] .form-check-input", - "selectUsersBtn": ".justify-content-end > .btn-primary" -} - -const dialogModerator = { - "openDialog": "#moderators", - "dialog": ".modal.show > .modal-dialog > .modal-content", - "searchBtn": ".modal.show > .modal-dialog > .modal-content > .modal-body > :nth-child(1) > .col-lg-4 > :nth-child(1)", - "selectUser": "[data-column-id=\"user-selection\"] .form-check-input", - "selectUsersBtn": ".justify-content-end > .btn-primary" -} +import { addEditSelectors, viewSelectors } from './selectors' export function selectVendor(vendorInputData) { - cy.openDialog(dialogVendor.openDialog, dialogVendor.dialog) - cy.selectOrAddVendor(dialogVendor, vendorInputData) + cy.openDialog(addEditSelectors.dialogVendor.openDialog, addEditSelectors.dialogVendor.dialog) + cy.selectOrAddVendor(addEditSelectors.dialogVendor, vendorInputData) } export function fillDataComponent(dataTest, isUpdate) { @@ -56,52 +32,52 @@ export function fillDataComponent(dataTest, isUpdate) { case 'description': case 'owner_accounting_unit': case 'owner_billing_group': - cy.get('#' + keyFieldName) + cy.get(addEditSelectors.fillData(keyFieldName)) .clear() .type(fieldValue) break case 'component_type': case 'country': - cy.get('#' + keyFieldName) + cy.get(addEditSelectors.fillData(keyFieldName)) .select(fieldValue.name) break case 'default_vendor': selectVendor(fieldValue) break case 'homeurl': - cy.get('#tag') + cy.get(addEditSelectors.txtHomeUrl) .clear() .type(dataTest.homeurl) break case 'component_owner': - cy.selectOneUser(dialogOwner,fieldValue.user_no) + cy.selectOneUser(addEditSelectors.dialogOwner,fieldValue.user_no) break case 'moderators': if (isUpdate == true) { - cy.get(':nth-child(1) > :nth-child(1) > .col > .mb-4 > :nth-child(4) > :nth-child(2) > span').click() - cy.selectMultiUsers(dialogModerator,fieldValue.num_user) + cy.get(addEditSelectors.btnDeleteAllModerators).click() + cy.selectMultiUsers(addEditSelectors.dialogModerator,fieldValue.num_user) break } else { - cy.selectMultiUsers(dialogModerator,fieldValue.num_user) + cy.selectMultiUsers(addEditSelectors.dialogModerator,fieldValue.num_user) break } case 'additional_roles': // additional_roles is skipped because bug in new front end break case 'external_id': - cy.get(':nth-child(4) > .row > .col-lg-4 > .btn') + cy.get(addEditSelectors.addRowExternalId.btnAddRow) .click() - cy.get('.form-control[aria-describedby="external id key"]').last() + cy.get(addEditSelectors.addRowExternalId.key).last() .type(fieldValue.key) - cy.get('.form-control[aria-describedby="external id value"]').last() + cy.get(addEditSelectors.addRowExternalId.value).last() .type(fieldValue.value) break case 'additional_data': - cy.get(':nth-child(5) > .row > .col-lg-4 > .btn') + cy.get(addEditSelectors.addRowAdditionalData.btnAddRow) .click() - cy.get('.form-control[aria-describedby="additional data key"]').last() + cy.get(addEditSelectors.addRowAdditionalData.key).last() .type(fieldValue.key) - cy.get('.form-control[aria-describedby="additional data value"]').last() + cy.get(addEditSelectors.addRowAdditionalData.value).last() .type(fieldValue.value) break default: @@ -111,18 +87,18 @@ export function fillDataComponent(dataTest, isUpdate) { } export function registerSimpleComponent(componentName, categories, conponentType) { - cy.get('[href="/components"]').click() + cy.get(viewSelectors.navComponents).click() cy.contains('Add Component').click() cy.url().should('include', '/components/add') - cy.get('#name').type(componentName) - cy.get('#categories').type(categories) - cy.get('#component_type').select(conponentType) - cy.get('.btn-toolbar button[type="submit"]').click() + cy.get(addEditSelectors.fillData('name')).type(componentName) + cy.get(addEditSelectors.fillData('categories')).type(categories) + cy.get(addEditSelectors.fillData('component_type')).select(conponentType) + cy.get(addEditSelectors.btnCreateComponent).click() cy.contains('Update Component') } export function gotoRegisterComponentPage() { - cy.get('[href="/components"]').click() + cy.get(viewSelectors.navComponents).click() cy.contains('Add Component').click() cy.url().should('include', '/components/add') } @@ -130,19 +106,20 @@ export function gotoRegisterComponentPage() { export function gotoViewComponentPage(componentName) { cy.visit(`${Cypress.env('sw360_base_url')}/components`) cy.contains('Add Component') - cy.get('[style="margin-bottom: 20px;"] > .col').should('be.visible') - cy.get('[data-column-id="name"] > div > .link').contains(componentName).invoke('attr', 'href').then((href) => { + cy.get(viewSelectors.tblComponentList).should('be.visible') + cy.get(viewSelectors.hyperlinkComponentNames).contains(componentName).invoke('attr', 'href').then((href) => { let component_id = href.split('/')[3] let viewUrl = "/components/detail/" + component_id cy.get(`a[href="${viewUrl}"]`).click() }) + cy.contains('Edit component') } export function gotoUpdateComponentPage(componentName) { - cy.get('[href="/components"]').click() + cy.get(viewSelectors.navComponents).click() cy.contains('Add Component') - cy.get('[style="margin-bottom: 20px;"] > .col').should('be.visible') - cy.get('[data-column-id="name"] > div > .link').contains(componentName).invoke('attr', 'href').then((href) => { + cy.get(viewSelectors.tblComponentList).should('be.visible') + cy.get(viewSelectors.hyperlinkComponentNames).contains(componentName).invoke('attr', 'href').then((href) => { let component_id = href.split('/')[3] let viewUrl = "/components/detail/" + component_id let editUrl = "/components/edit/" + component_id @@ -158,19 +135,19 @@ export function registerComponent(testId) { const dataTest = component[testId] fillDataComponent(dataTest, false) }) - cy.get('.btn-toolbar button[type="submit"]').click() + cy.get(addEditSelectors.btnCreateComponent).click() } export function gotoUpdateReleasePageFromViewComponentPage(releaseVersion) { - cy.get('#tab-Releases').click() - cy.get(':nth-child(3) > .row > :nth-child(2) > .gridjs').should('be.visible') + cy.get(viewSelectors.tabReleaseOverview).click() + cy.get(viewSelectors.tblReleasesList.table).should('be.visible') cy.contains(releaseVersion).closest('tr').find('td').last().find('svg').first().click() } export function gotoViewReleasePageFromViewComponentPage(releaseVersion) { - cy.get('#tab-Releases').click() - cy.get(':nth-child(3) > .row > :nth-child(2) > .gridjs').should('be.visible') + cy.get(viewSelectors.tabReleaseOverview).click() + cy.get(viewSelectors.tblReleasesList.table).should('be.visible') cy.get('a:contains(' + releaseVersion + ')').click() } diff --git a/cypress/e2e/releases/link-to-project.cy.js b/cypress/e2e/releases/link-to-project.cy.js index a84d26d02..07dab0869 100644 --- a/cypress/e2e/releases/link-to-project.cy.js +++ b/cypress/e2e/releases/link-to-project.cy.js @@ -8,31 +8,32 @@ // SPDX-License-Identifier: EPL-2.0 // License-Filename: LICENSE +import { viewSelectors } from './selectors' + const verifySuccessMessage = (testData) => { - cy.get('.alert.alert-success').contains(`The release ${testData.release.name}(${testData.release.version}) has been successfully linked to project ${testData.linkedProject.name}`) - cy.get('.alert.alert-success').contains('Click here to edit the release relation as well as the project mainline state in the project') + cy.get(viewSelectors.linkToPJSuccessMessage).contains(`The release ${testData.release.name}(${testData.release.version}) has been successfully linked to project ${testData.linkedProject.name}`) + cy.get(viewSelectors.linkToPJSuccessMessage).contains('Click here to edit the release relation as well as the project mainline state in the project') } const openLinkModal = (release, isComponentPage) => { cy.get(`a:contains("${release.name}")`).click() - cy.get('#tab-Releases').click() + cy.get(viewSelectors.tabReleaseOverview).click() if (isComponentPage) { cy.get(`a:contains("${release.version}")`).closest('tr').find('td').last().find('svg').eq(1).click() } else { cy.get(`a:contains("${release.version}")`).click() - cy.get('.btn-group > :nth-child(2) > .btn').click() + cy.get(viewSelectors.btnLinkToProject).click() } } const selectProjectToLink = (linkedProject) => { - cy.get('.col-lg-3 > .btn').click() + cy.get(viewSelectors.dialogLinkReleaseToProject.btnSearch).click() cy.get('table tr').contains('td:eq(1)', linkedProject.name).parent('tr').within(() => { cy.get('td:eq(2)').should('contain', linkedProject.version); }).find('td').first().find('div').find('.form-check-input').click() - cy.get('.justify-content-end button').last().click() + cy.get(viewSelectors.dialogLinkReleaseToProject.btnsCloseAndLinkToProject).last().click() } - const createComponent = (name, componentType, categories) => { return cy.createComponent(name, componentType, categories).then((component) => component.id) } diff --git a/cypress/e2e/releases/selectors.js b/cypress/e2e/releases/selectors.js new file mode 100644 index 000000000..8c269cd84 --- /dev/null +++ b/cypress/e2e/releases/selectors.js @@ -0,0 +1,139 @@ +// Copyright (C) TOSHIBA CORPORATION, 2024. Part of the SW360 Frontend Project. +// Copyright (C) Toshiba Software Development (Vietnam) Co., Ltd., 2024. Part of the SW360 Frontend Project. + +// This program and the accompanying materials are made +// available under the terms of the Eclipse Public License 2.0 +// which is available at https://www.eclipse.org/legal/epl-2.0/ + +// SPDX-License-Identifier: EPL-2.0 +// License-Filename: LICENSE + +// elements of add/edit release page +export const addEditSelectors = { + tabReleaseOverview: '#tab-releases', + btnAddRelease: '.container > :nth-child(1) > :nth-child(2) > :nth-child(3) > :nth-child(2) > .fw-bold', + btnCreateRelease: '[href=""] > .btn', + btnUpdateRelease: '.btn-group > :nth-child(1) > .btn', + + // Summary tab + txtName: '#name', + txtVersion: ':nth-child(3) > #version', + txtProgrammingLanguages: '#programming_languages', + txtOperatingSystems: '#operating_systems', + txtCpeid: '#tag', + txtSoftwarePlatforms: '#blog_url', + txtSrcDownloadUrl: '#wiki_url', + txtBinaryDownloadUrl: '#binaryDownloadurl', + sltReleaseMainlineState: '#mainlineState', + dialogVendor: { + "openDialog": "#default_vendor", + "dialog": ".modal-content", + "addVendorBtn": ".justify-content-end > :nth-child(2)", + "addVendorBtnInAddVendorDialog": "", + "searchBtn": ":nth-child(1) > .col-lg-4 > :nth-child(1)", + "selectUser": "[data-column-id=\"vendorId\"] > :nth-child(1) > div > .form-check-input", + "selectVendorBtn": ".justify-content-end > :nth-child(3)", + "givenName": "[data-column-id=\"fullName\"]", + "lastName": "[data-column-id=\"shortName\"]", + }, + + dialogModerator: { + "openDialog": "#moderators", + "dialog": ".modal-content", + "searchBtn": ":nth-child(1) > .col-lg-4 > :nth-child(1)", + "selectUser": "[data-column-id=\"user-selection\"] > :nth-child(1) > div > .form-check-input", + "selectUsersBtn": ".justify-content-end > .btn-primary", + "givenName": "[data-column-id=\"GivenName\"]", + "lastName": "[data-column-id=\"LastName\"]", + + }, + + dialogContributor: { + "openDialog": "#contributors", + "dialog": ".modal-content", + "searchBtn": ":nth-child(1) > .col-lg-4 > :nth-child(1)", + "selectUser": "[data-column-id=\"user-selection\"] > :nth-child(1) > div > .form-check-input", + "selectUsersBtn": ".justify-content-end > :nth-child(2)", + "givenName": "[data-column-id=\"givenName\"]", + "lastName": "[data-column-id=\"lastName\"]", + }, + + dialogOtherLicense: { + "openDialog": "#otherLicenseIds", + "dialog": ".modal-content", + "searchBtn": ":nth-child(1) > .col-lg-4 > :nth-child(1)", + "selectLicense": "[data-column-id=\"licenseId\"] > :nth-child(1) > div > .form-check-input", + "selectLicenseBtn": ".justify-content-end > :nth-child(2)", + "givenName": "[data-column-id=\"fullName\"]" + }, + + dialogMainLicense: { + "openDialog": "#mainLicenseIds", + "dialog": ".modal-content", + "searchBtn": ":nth-child(1) > .col-lg-4 > :nth-child(1)", + "selectLicense": "[data-column-id=\"licenseId\"] > :nth-child(1) > div > .form-check-input", + "selectLicenseBtn": ".justify-content-end > :nth-child(2)", + "givenName": "[data-column-id=\"license\"]" + }, + + addRowAdditionalRoles: { + 'btnAddRow': '.row > .row > .col-lg-4 > .btn', + 'key': ':nth-child(2) > .row > :nth-child(1) > .form-select', + 'value': ':nth-child(2) > :nth-child(2) > .row > :nth-child(2) > .form-control' + }, + + addRowExternalId: { + 'btnAddRow': ':nth-child(3) > .row > .col-lg-4 > .btn', + 'key': '.col-lg-6 > .form-control', + 'value': ':nth-child(3) > :nth-child(2) > .row > .col-lg-5 > .form-control' + }, + + addRowAdditionalData: { + 'btnAddRow': ':nth-child(4) > .row > .col-lg-4 > .btn', + 'key': ':nth-child(4) > :nth-child(2) > .row > .col-lg-6 > .form-control', + 'value': ':nth-child(4) > :nth-child(2) > .row > .col-lg-5 > .form-control' + }, + + releaseRepository: { + sltRepositoryType: '#repository_type', + txtRepositoryUrl: ':nth-child(2) > #version' + }, + + // Attachments tab + dialogAddAttachment: { + tabAttachments: '#tab-Attachments', + openDialog: '.page-content > :nth-child(1) > :nth-child(2) > :nth-child(6) > :nth-child(2) > .fw-bold', + dialog: '.modal-content', + removePreUploadFileInDialog: ':nth-child(1) > .SelectAttachment_button-delete__QEfUR > .btn', + btnUpload: '.button-orange', + tblAttachFileList: '.Attachment_attachment-table__T7Kx_' + }, + + // Clearing Details tab + tabClearingDetails: '#tab-ClearingDetails', + fillDataClearingDetails: (key) => `#${key}`, + + // ECC Details tab + tabEccDetails: '#tab-EccDetails', + sltEccStatus: '#ECC_Status', + fillDataECCDetails: (key) => `#${key}`, + + +} +//elements of view page +export const viewSelectors = { + tabReleaseOverview: '#tab-Releases', + hyperlinkComponentNames: '[data-column-id="name"] > div > .link', + sltVersion: '[id^="react-aria"]', + btnLinkToProject: '.btn-group > :nth-child(2) > .btn', + dialogLinkReleaseToProject: { + btnSearch: '.col-lg-3 > .btn', + btnsCloseAndLinkToProject: '.justify-content-end button' + }, + + // Summary tab + cpeid: ':nth-child(2) > :nth-child(1) > tbody > :nth-child(2) > :nth-child(2)', + + // SuccessMessage when link release to project + linkToPJSuccessMessage: '.alert.alert-success' +} diff --git a/cypress/e2e/releases/utils.js b/cypress/e2e/releases/utils.js index 952a83510..22ae118bc 100644 --- a/cypress/e2e/releases/utils.js +++ b/cypress/e2e/releases/utils.js @@ -8,60 +8,11 @@ // SPDX-License-Identifier: EPL-2.0 // License-Filename: LICENSE -const dialogVendor = { - "openDialog": "#default_vendor", - "dialog": ".modal-content", - "addVendorBtn": ".justify-content-end > :nth-child(2)", - "addVendorBtnInAddVendorDialog": "", - "searchBtn": ":nth-child(1) > .col-lg-4 > :nth-child(1)", - "selectUser": "[data-column-id=\"vendorId\"] > :nth-child(1) > div > .form-check-input", - "selectVendorBtn": ".justify-content-end > :nth-child(3)", - "givenName": "[data-column-id=\"fullName\"]", - "lastName": "[data-column-id=\"shortName\"]", -} - -const dialogModerator = { - "openDialog": "#moderators", - "dialog": ".modal-content", - "searchBtn": ":nth-child(1) > .col-lg-4 > :nth-child(1)", - "selectUser": "[data-column-id=\"user-selection\"] > :nth-child(1) > div > .form-check-input", - "selectUsersBtn": ".justify-content-end > .btn-primary", - "givenName": "[data-column-id=\"GivenName\"]", - "lastName": "[data-column-id=\"LastName\"]", - -} - -const dialogContributor = { - "openDialog": "#contributors", - "dialog": ".modal-content", - "searchBtn": ":nth-child(1) > .col-lg-4 > :nth-child(1)", - "selectUser": "[data-column-id=\"user-selection\"] > :nth-child(1) > div > .form-check-input", - "selectUsersBtn": ".justify-content-end > :nth-child(2)", - "givenName": "[data-column-id=\"givenName\"]", - "lastName": "[data-column-id=\"lastName\"]", -} - -const dialogOtherLicense = { - "openDialog": "#otherLicenseIds", - "dialog": ".modal-content", - "searchBtn": ":nth-child(1) > .col-lg-4 > :nth-child(1)", - "selectLicense": "[data-column-id=\"licenseId\"] > :nth-child(1) > div > .form-check-input", - "selectLicenseBtn": ".justify-content-end > :nth-child(2)", - "givenName": "[data-column-id=\"fullName\"]" -} - -const dialogMainLicense = { - "openDialog": "#mainLicenseIds", - "dialog": ".modal-content", - "searchBtn": ":nth-child(1) > .col-lg-4 > :nth-child(1)", - "selectLicense": "[data-column-id=\"licenseId\"] > :nth-child(1) > div > .form-check-input", - "selectLicenseBtn": ".justify-content-end > :nth-child(2)", - "givenName": "[data-column-id=\"license\"]" -} +import { addEditSelectors, viewSelectors } from './selectors' export function selectVendor(vendorInputData) { - cy.openDialog(dialogVendor.openDialog, dialogVendor.dialog) - cy.selectOrAddVendor(dialogVendor, vendorInputData) + cy.openDialog(addEditSelectors.dialogVendor.openDialog, addEditSelectors.dialogVendor.dialog) + cy.selectOrAddVendor(addEditSelectors.dialogVendor, vendorInputData) } export function selectLicenses(dialogLicense, licenseInputData) { @@ -75,13 +26,13 @@ export function selectLicenses(dialogLicense, licenseInputData) { } export function gotoRegisterReleasePage() { - cy.get('#tab-releases').click() - cy.get('.container > :nth-child(1) > :nth-child(2) > :nth-child(3) > :nth-child(2) > .fw-bold').click() + cy.get(addEditSelectors.tabReleaseOverview).click() + cy.get(addEditSelectors.btnAddRelease).click() cy.contains('Create Release') } export function fillDataRelease(dataTest) { - cy.get('#name').should('not.have.value', '') + cy.get(addEditSelectors.txtName).should('not.have.value', '') cy.log('------Fill datatest------') const nStep = Object.keys(dataTest).length for (let i = 0; i < nStep; i++) { @@ -92,23 +43,27 @@ export function fillDataRelease(dataTest) { selectVendor(fieldValue) break case 'version': - cy.get(':nth-child(3) > #version') + cy.get(addEditSelectors.txtVersion) .clear() .type(fieldValue) break case 'programming_languages': + cy.get(addEditSelectors.txtProgrammingLanguages) + .clear() + .type(fieldValue) + break case 'operating_systems': - cy.get('#' + keyFieldName) + cy.get(addEditSelectors.txtOperatingSystems) .clear() .type(fieldValue) break case 'cpeid': - cy.get('#tag') + cy.get(addEditSelectors.txtCpeid) .clear() .type(fieldValue) break case 'software_platforms': - cy.get('#blog_url') + cy.get(addEditSelectors.txtSoftwarePlatforms) .clear() .type(fieldValue) break @@ -116,64 +71,64 @@ export function fillDataRelease(dataTest) { // Skip break case 'main_license': - selectLicenses(dialogMainLicense,fieldValue) + selectLicenses(addEditSelectors.dialogMainLicense,fieldValue) break case 'other_license': - selectLicenses(dialogOtherLicense,fieldValue) + selectLicenses(addEditSelectors.dialogOtherLicense,fieldValue) break case 'src_download_url': - cy.get('#wiki_url') + cy.get(addEditSelectors.txtSrcDownloadUrl) .clear() .type(fieldValue) break case 'binary_download_url': - cy.get('#binaryDownloadurl') + cy.get(addEditSelectors.txtBinaryDownloadUrl) .clear() .type(fieldValue) break - case 'releasemainlinestate': - cy.get('#mainlineState') + case 'release_mainline_state': + cy.get(addEditSelectors.sltReleaseMainlineState) .select(fieldValue.name) break case 'contributors': - cy.selectMultiUsers(dialogContributor,fieldValue.num_user) + cy.selectMultiUsers(addEditSelectors.dialogContributor,fieldValue.num_user) break case 'moderators': - cy.selectMultiUsers(dialogModerator,fieldValue.num_user) + cy.selectMultiUsers(addEditSelectors.dialogModerator,fieldValue.num_user) break case 'additional_roles': - cy.get('.row > .row > .col-lg-4 > .btn') + cy.get(addEditSelectors.addRowAdditionalRoles.btnAddRow) .eq(0).click() - cy.get(':nth-child(2) > .row > :nth-child(1) > .form-select') + cy.get(addEditSelectors.addRowAdditionalRoles.key) .select(fieldValue.role.name) - cy.get(':nth-child(2) > :nth-child(2) > .row > :nth-child(2) > .form-control') + cy.get(addEditSelectors.addRowAdditionalRoles.value) .clear() .type(fieldValue.mail_address) break case 'external_id': - cy.get(':nth-child(3) > .row > .col-lg-4 > .btn') + cy.get(addEditSelectors.addRowExternalId.btnAddRow) .click() - cy.get('.col-lg-6 > .form-control') + cy.get(addEditSelectors.addRowExternalId.key) .clear() .type(fieldValue.key) - cy.get(':nth-child(3) > :nth-child(2) > .row > .col-lg-5 > .form-control') + cy.get(addEditSelectors.addRowExternalId.value) .clear() .type(fieldValue.value) break case 'additional_data': - cy.get(':nth-child(4) > .row > .col-lg-4 > .btn') + cy.get(addEditSelectors.addRowAdditionalData.btnAddRow) .click() - cy.get(':nth-child(4) > :nth-child(2) > .row > .col-lg-6 > .form-control') + cy.get(addEditSelectors.addRowAdditionalData.key) .clear() .type(fieldValue.key) - cy.get(':nth-child(4) > :nth-child(2) > .row > .col-lg-5 > .form-control') + cy.get(addEditSelectors.addRowAdditionalData.value) .clear() .type(fieldValue.value) break case 'release_repository': - cy.get('#repository_type') + cy.get(addEditSelectors.releaseRepository.sltRepositoryType) .select(fieldValue.repository_type.name) - cy.get(':nth-child(2) > #version') + cy.get(addEditSelectors.releaseRepository.txtRepositoryUrl) .clear() .type(fieldValue.repository_URL) break @@ -185,7 +140,7 @@ export function fillDataRelease(dataTest) { function verifyReleaseAfterCreated(testId) { cy.log('[Info] Validate Release after created') - cy.get('.btn-group> :nth-child(1) > .btn') + cy.get(addEditSelectors.btnUpdateRelease) .contains('Update Release') cy.fixture('releases/register').then((release) => { const dataTest = release[testId] @@ -198,14 +153,14 @@ function verifyReleaseAfterCreated(testId) { // Skip break case 'version': - cy.get(':nth-child(3) > #version') + cy.get(addEditSelectors.txtVersion) .should('have.value', fieldValue) break case 'programming_languages': // Skip break case 'operating_systems': - cy.get('#' + keyFieldName) + cy.get(addEditSelectors.txtOperatingSystems) .should('have.value', fieldValue) break case 'cpeid': @@ -221,15 +176,15 @@ function verifyReleaseAfterCreated(testId) { // Skip break case 'src_download_url': - cy.get('#wiki_url') + cy.get(addEditSelectors.txtSrcDownloadUrl) .should('have.value', fieldValue) break case 'binary_download_url': - cy.get('#binaryDownloadurl') + cy.get(addEditSelectors.txtBinaryDownloadUrl) .should('have.value', fieldValue) break - case 'releasemainlinestate': - cy.get('#mainlineState') + case 'release_mainline_state': + cy.get(addEditSelectors.sltReleaseMainlineState) .should('have.value', fieldValue.value) break case 'contributors': @@ -239,27 +194,27 @@ function verifyReleaseAfterCreated(testId) { // Skip break case 'additional_roles': - cy.get(':nth-child(2) > .row > :nth-child(1) > .form-select') + cy.get(addEditSelectors.addRowAdditionalRoles.key) .should('have.value', fieldValue.role.name) - cy.get(':nth-child(2) > :nth-child(2) > .row > :nth-child(2) > .form-control') + cy.get(addEditSelectors.addRowAdditionalRoles.value) .should('have.value', fieldValue.mail_address) break case 'external_id': - cy.get('.col-lg-6 > .form-control') + cy.get(addEditSelectors.addRowExternalId.key) .should('have.value', fieldValue.key) - cy.get(':nth-child(3) > :nth-child(2) > .row > .col-lg-5 > .form-control') + cy.get(addEditSelectors.addRowExternalId.value) .should('have.value', fieldValue.value) break case 'additional_data': - cy.get(':nth-child(4) > :nth-child(2) > .row > .col-lg-6 > .form-control') + cy.get(addEditSelectors.addRowAdditionalData.key) .should('have.value', fieldValue.key) - cy.get(':nth-child(4) > :nth-child(2) > .row > .col-lg-5 > .form-control') + cy.get(addEditSelectors.addRowAdditionalData.value) .should('have.value', fieldValue.value) break case 'release_repository': - cy.get('#repository_type') + cy.get(addEditSelectors.releaseRepository.sltRepositoryType) .should('have.value', fieldValue.repository_type.value) - cy.get(':nth-child(2) > #version') + cy.get(addEditSelectors.releaseRepository.txtRepositoryUrl) .should('have.value', fieldValue.repository_URL) break default: @@ -271,9 +226,9 @@ function verifyReleaseAfterCreated(testId) { export function registerSimpleRelease(releaseVersion) { gotoRegisterReleasePage() - cy.get(':nth-child(3) > #version') + cy.get(addEditSelectors.txtVersion) .type(releaseVersion) - cy.get('[href=""] > .btn') + cy.get(addEditSelectors.btnCreateRelease) .click() cy.contains('Update Release') } @@ -284,7 +239,7 @@ export function registerRelease(testId) { const dataTest = release[testId] fillDataRelease(dataTest) }) - cy.get('[href=""] > .btn') + cy.get(addEditSelectors.btnCreateRelease) .click() } @@ -294,21 +249,18 @@ export function registerAndVerifyRelease(testId) { } function addAttachment(fileNames, shouldUnAttachFile) { - let openDialog = '.page-content > :nth-child(1) > :nth-child(2) > :nth-child(6) > :nth-child(2) > .fw-bold' - let dialog = '.modal-content' - cy.openDialog(openDialog, dialog) - + cy.openDialog(addEditSelectors.dialogAddAttachment.openDialog, addEditSelectors.dialogAddAttachment.dialog) cy.get('input[type=file]').selectFile(fileNames, { force: true }) if (shouldUnAttachFile == true) { - cy.get(':nth-child(1) > .SelectAttachment_button-delete__QEfUR > .btn').click() + cy.get(addEditSelectors.dialogAddAttachment.removePreUploadFileInDialog).click() } - cy.get('.button-orange').click() - cy.get('.Attachment_attachment-table__T7Kx_').should('be.visible') + cy.get(addEditSelectors.dialogAddAttachment.btnUpload).click() + cy.get(addEditSelectors.dialogAddAttachment.tblAttachFileList).should('be.visible') } function uploadAttachment(dataTest) { - cy.get('#tab-Attachments').click() + cy.get(addEditSelectors.dialogAddAttachment.tabAttachments).click() cy.contains('Add Attachment') let attachmentLength = Object.keys(dataTest).length for (let i = 0; i < attachmentLength; i++) { @@ -339,7 +291,7 @@ function uploadAttachment(dataTest) { function updateClearingDetails(dataTest) { cy.log('[Info] Fill test data on clearing details page') - cy.get('#tab-ClearingDetails').click() + cy.get(addEditSelectors.tabClearingDetails).click() cy.contains('Clearing Details') const nStep = Object.keys(dataTest).length for (let i = 0; i < nStep; i++) { @@ -360,8 +312,8 @@ function updateClearingDetails(dataTest) { case 'license_agreement': case 'component_clearing_report': if (fieldValue == true) { - cy.get('#' + keyFieldName).check() - } else cy.get('#' + keyFieldName).uncheck() + cy.get(addEditSelectors.fillDataClearingDetails(keyFieldName)).check() + } else cy.get(addEditSelectors.fillDataClearingDetails(keyFieldName)).uncheck() break case 'scanned': case 'clearing_standard': @@ -371,7 +323,7 @@ function updateClearingDetails(dataTest) { case 'additional_request_info': case 'external_supplier_id': case 'count_security_vulnerabilities': - cy.get('#' + keyFieldName) + cy.get(addEditSelectors.fillDataClearingDetails(keyFieldName)) .clear() .type(fieldValue) case 'evaluation_start': @@ -386,7 +338,7 @@ function updateClearingDetails(dataTest) { function updateECCDetails(dataTest) { cy.log('[Info] Fill test data on clearing details page') - cy.get('#tab-EccDetails').click() + cy.get(addEditSelectors.tabEccDetails).click() cy.contains('ECC Information') const nStep = Object.keys(dataTest).length for (let i = 0; i < nStep; i++) { @@ -394,13 +346,13 @@ function updateECCDetails(dataTest) { const fieldValue = dataTest[keyFieldName] switch (keyFieldName) { case 'ECC_status': - cy.get('#ECC_Status').select(fieldValue.name) + cy.get(addEditSelectors.sltEccStatus).select(fieldValue.name) break case 'ECC_comment': case 'ausfuhrliste': case 'eccn': case 'material_index_number': - cy.get('#' + keyFieldName).clear() + cy.get(addEditSelectors.fillDataECCDetails(keyFieldName)).clear() .type(fieldValue) break default: @@ -440,11 +392,11 @@ function verifyReleaseAfterUpdate(dataTest) { const fieldValue = dataTest[keyFieldName] switch (keyFieldName) { case 'version': - cy.get('#react-aria4178382462-\:r2\:') + cy.get(viewSelectors.sltVersion) .should('have.text', 'Version ' + fieldValue) break case 'cpeid': - cy.get(':nth-child(2) > :nth-child(1) > tbody > :nth-child(2) > :nth-child(2)') + cy.get(viewSelectors.cpeid) .should('have.text', fieldValue) break default: @@ -465,7 +417,7 @@ export function updateRelease(testId) { cy.fixture('releases/update').then((release) => { const dataTest = release[testId] fillUpdatedData(dataTest) - cy.get('.btn-group > :nth-child(1) > .btn').click({ force: true }) + cy.get(addEditSelectors.btnUpdateRelease).click({ force: true }) }) } @@ -473,7 +425,7 @@ export function updateAndVerifyReleaseAfterUpdate(testId) { cy.fixture('releases/update').then((release) => { const dataTest = release[testId] fillUpdatedData(dataTest) - cy.get('.btn-group > :nth-child(1) > .btn').click({ force: true }) + cy.get(addEditSelectors.btnUpdateRelease).click({ force: true }) verifyReleaseAfterUpdate(dataTest) }) } diff --git a/cypress/fixtures/releases/register.json b/cypress/fixtures/releases/register.json index c9c293ad5..a0289a70e 100644 --- a/cypress/fixtures/releases/register.json +++ b/cypress/fixtures/releases/register.json @@ -29,7 +29,7 @@ }, "src_download_url": "http://10.116.43.147:3000/components/releases/detail/", "binary_download_url": "https://chat.openai.com/", - "releasemainlinestate": { + "release_mainline_state": { "name": "Mainline", "value": "MAINLINE" },