From 39ac5555a2bae998838188b401a4c2516d8099a8 Mon Sep 17 00:00:00 2001 From: maipt Date: Thu, 9 May 2024 13:55:35 +0700 Subject: [PATCH] feat(Cypress): Add test script for licenses page Signed-off-by: hoangnt2 --- .../e2e/components/export-spreadsheet.cy.js | 7 +- cypress/e2e/components/utils.js | 1 - cypress/e2e/licenses/delete.cy.js | 54 ++++++ cypress/e2e/licenses/export-spreadsheet.cy.js | 30 +++ cypress/e2e/licenses/register.cy.js | 121 ++++++++++++ cypress/e2e/licenses/selectors.js | 115 +++++++++++ cypress/e2e/licenses/update.cy.js | 63 ++++++ cypress/e2e/licenses/utils.js | 183 ++++++++++++++++++ cypress/fixtures/licenses/delete.json | 6 + cypress/fixtures/licenses/register.json | 42 ++++ cypress/fixtures/licenses/update.json | 32 +++ cypress/support/commands.js | 46 ++++- cypress/support/common.sh | 79 ++++++++ cypress/support/e2e.ts | 2 +- cypress/support/tasks.ts | 57 ++++-- 15 files changed, 819 insertions(+), 19 deletions(-) create mode 100644 cypress/e2e/licenses/delete.cy.js create mode 100644 cypress/e2e/licenses/export-spreadsheet.cy.js create mode 100644 cypress/e2e/licenses/register.cy.js create mode 100644 cypress/e2e/licenses/selectors.js create mode 100644 cypress/e2e/licenses/update.cy.js create mode 100644 cypress/e2e/licenses/utils.js create mode 100644 cypress/fixtures/licenses/delete.json create mode 100644 cypress/fixtures/licenses/register.json create mode 100644 cypress/fixtures/licenses/update.json diff --git a/cypress/e2e/components/export-spreadsheet.cy.js b/cypress/e2e/components/export-spreadsheet.cy.js index 83591fcca..bfc916bcd 100644 --- a/cypress/e2e/components/export-spreadsheet.cy.js +++ b/cypress/e2e/components/export-spreadsheet.cy.js @@ -12,27 +12,26 @@ import { viewSelectors } from './selectors' const verifyFileExported = () => { const currentDate = new Date().toISOString().split("T")[0] - cy.readFile(`cypress/downloads/components-${currentDate}.xlsx`) - .should('exist') + const downloadedFileName = `components-${currentDate}.xlsx` + cy.verifyDownloadedFile(downloadedFileName) } describe('Export Spreadsheet', () => { beforeEach(() => { cy.login('admin') cy.visit(`${Cypress.env('sw360_base_url')}/components`) + cy.removeDownloadsFolder() }) it('TC13: Export components without releases', () => { cy.get(viewSelectors.btnExportSpreadsheet).click() cy.get(viewSelectors.btnExportComponentsOnly).click() verifyFileExported() - cy.removeDownloadedFiles() }) it('TC14: Export components with releases', () => { cy.get(viewSelectors.btnExportSpreadsheet).click() cy.get(viewSelectors.btnExportComponentsWithReleases).click() verifyFileExported() - cy.removeDownloadedFiles() }) }) diff --git a/cypress/e2e/components/utils.js b/cypress/e2e/components/utils.js index 7ac4f31c1..738e8f9f2 100644 --- a/cypress/e2e/components/utils.js +++ b/cypress/e2e/components/utils.js @@ -144,7 +144,6 @@ export function gotoUpdateReleasePageFromViewComponentPage(releaseVersion) { cy.contains(releaseVersion).closest('tr').find('td').last().find('svg').first().click() } - export function gotoViewReleasePageFromViewComponentPage(releaseVersion) { cy.get(viewSelectors.tabReleaseOverview).click() cy.get(viewSelectors.tblReleasesList.table).should('be.visible') diff --git a/cypress/e2e/licenses/delete.cy.js b/cypress/e2e/licenses/delete.cy.js new file mode 100644 index 000000000..4a03d1b0e --- /dev/null +++ b/cypress/e2e/licenses/delete.cy.js @@ -0,0 +1,54 @@ +// 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 + +import { addEditSelectors, viewSelectors } from './selectors' +import { deleteLicensesBeforeRegisterUpdate, gotoUpdateLicensePage } from './utils' + +function deleteLicense() { + cy.get(addEditSelectors.btnDeleteLicense).click() + cy.get(addEditSelectors.dlgDeleteLicense.dialog).should('be.visible') + .then(() => { + cy.get(addEditSelectors.dlgDeleteLicense.btnDeleteLicense).click() + }) + cy.get(addEditSelectors.dlgDeleteLicense.dialog).should('not.exist') + cy.get(viewSelectors.alertMessage).contains('Success: License removed successfully!') +} + +function verifyDeletedLicense(licenseShortName) { + cy.get(viewSelectors.tblLicenseList).then(() => { + cy.contains('a', licenseShortName).should('not.exist') + }) +} + +describe('Delete a license', () => { + + before(() => { + deleteLicensesBeforeRegisterUpdate('licenses/update', true) + cy.fixture('licenses/delete').then((license) => { + const fullName = license['TC05_DELETE_LICENSE'].full_name + const shortName = license['TC05_DELETE_LICENSE'].short_name + cy.createLicenseByAPI(fullName, shortName) + }) + }) + + beforeEach(() => { + cy.login('admin') + }) + + it('TC05: Delete an existing license', () => { + cy.fixture('licenses/delete').then((license) => { + const shortName = license['TC05_DELETE_LICENSE'].short_name + // todo search a license by quick filter + gotoUpdateLicensePage(shortName) + deleteLicense() + verifyDeletedLicense(shortName) + }) + }) +}) \ No newline at end of file diff --git a/cypress/e2e/licenses/export-spreadsheet.cy.js b/cypress/e2e/licenses/export-spreadsheet.cy.js new file mode 100644 index 000000000..9865f8df9 --- /dev/null +++ b/cypress/e2e/licenses/export-spreadsheet.cy.js @@ -0,0 +1,30 @@ +// 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 + +import { viewSelectors } from './selectors' + +const verifyFileExported = () => { + const downloadedFileName = 'Licenses.xlsx' + cy.verifyDownloadedFile(downloadedFileName) +} + +describe('Export License', () => { + beforeEach(() => { + cy.login('admin') + cy.visit(`${Cypress.env('sw360_base_url')}/licenses`) + cy.get(viewSelectors.tblLicenseList).should('be.visible') + cy.removeDownloadsFolder() + }) + + it('TC06: Check Export Licenses', () => { + cy.downloadFile(viewSelectors.btnExportSpreadsheet) + verifyFileExported() + }) +}) \ No newline at end of file diff --git a/cypress/e2e/licenses/register.cy.js b/cypress/e2e/licenses/register.cy.js new file mode 100644 index 000000000..03ea051d2 --- /dev/null +++ b/cypress/e2e/licenses/register.cy.js @@ -0,0 +1,121 @@ +// 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 + +import { viewSelectors } from './selectors' +import { registerLicense, verifyDetailsLicense, deleteLicensesBeforeRegisterUpdate } from './utils' + +function gotoLicenseDetailPage(licenseShortName) { + cy.contains('a', licenseShortName).as('liceseName') + cy.get('@liceseName').click() +} + +function verifyAddedLicenseInLicenseList(licenseShortName) { + cy.contains('a', licenseShortName).should('be.visible') +} + +function updateExternalLink(testData) { + cy.get(viewSelectors.externalLink).clear() + .type(testData) + cy.get(viewSelectors.btnSave).click() + cy.get(viewSelectors.alertMessage).contains(' Success: Update External Link Success!') + cy.get(viewSelectors.externalLink).should('have.value', testData) +} + +function selectWhiteList(testData) { + cy.get(viewSelectors.cbWhiteList).as('cbWhiteLists').then(($checkboxes) => { + const checkUncheckPromises = $checkboxes.map(($checkbox, index) => { + if (testData[index] === false) { + return cy.wrap($checkbox).uncheck({ force: true }).then(() => $checkbox) + } else if (testData[index] === true) { + return cy.wrap($checkbox).check({ force: true }).then(() => $checkbox) + } + }) + return Cypress.Promise.all(checkUncheckPromises); + }) +} + +function updateWhiteList(testData) { + cy.get(viewSelectors.tabObligations).click() + cy.get(viewSelectors.btnEditWhiteList).click() + cy.get(viewSelectors.tblUpdateWhiteList).should('be.visible') + selectWhiteList(testData) + cy.get(viewSelectors.btnUpdateWhiteList).click() + // todo verify ' Success: License updated successfully!') + cy.contains('button', 'Edit License').should('exist') +} + +function updateWhiteListAndVerify(testData) { + cy.get(viewSelectors.tabObligations).click() + cy.get(viewSelectors.btnEditWhiteList).click() + cy.get(viewSelectors.tblUpdateWhiteList).as('tblWhiteList').should('be.visible') + cy.wrap(selectWhiteList(testData)).then(() => { + let obligationsOutput = 0 + cy.get('@cbWhiteLists').each(($checkbox) => { + if ($checkbox.is(':checked')) { + obligationsOutput++ + } + }).then(() => { + cy.get(viewSelectors.btnUpdateWhiteList).click() + // todo verify ' Success: License updated successfully!') + cy.contains('button', 'Edit License').should('exist') + cy.get(viewSelectors.tabObligations).click() + cy.get(viewSelectors.tblLinkedObligations).as('tblLinkedObligations') + cy.get('@tblLinkedObligations').should('not.contain','No matching records found') + cy.get('@tblLinkedObligations').find('tr').should('have.length', obligationsOutput) + }) + }) +} + +describe('Register a license', () => { + + before(() => { + deleteLicensesBeforeRegisterUpdate('licenses/register', false) + }) + + beforeEach(() => { + cy.login('admin') + }) + + it('TC01: Create a license with mandatory fields then edit External link', () => { + cy.fixture('licenses/register').then((license) => { + const testData = license['TC01_REQUIRED_FIELDS'] + const licenseShortName = testData.license_tab.short_name + const externalLink = testData.external_link + registerLicense(testData) + verifyAddedLicenseInLicenseList(licenseShortName) + gotoLicenseDetailPage(licenseShortName) + updateExternalLink(externalLink) + verifyDetailsLicense(testData) + }) + }) + + it('TC02: Create a license with all fields', () => { + cy.fixture('licenses/register').then((license) => { + const testData = license['TC02_ALL_FIELDS'] + const licenseShortName = testData.license_tab.short_name + registerLicense(testData) + verifyAddedLicenseInLicenseList(licenseShortName) + gotoLicenseDetailPage(licenseShortName) + verifyDetailsLicense(testData) + }) + }) + + it('TC03: Create a license with linked obligations then edit whitelist', () => { + cy.fixture('licenses/register').then((license) => { + const testData = license['TC03_LINKED_OBLIGATION'] + const licenseShortName = testData.license_tab.short_name + registerLicense(testData) + // todo search a license by quick filter + verifyAddedLicenseInLicenseList(licenseShortName) + gotoLicenseDetailPage(licenseShortName) + updateWhiteListAndVerify(testData.update_white_list) + }) + }) +}) \ No newline at end of file diff --git a/cypress/e2e/licenses/selectors.js b/cypress/e2e/licenses/selectors.js new file mode 100644 index 000000000..8f7080703 --- /dev/null +++ b/cypress/e2e/licenses/selectors.js @@ -0,0 +1,115 @@ +// 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 page +const btnAddObligation = 'Add Obligation' +const btnCreateLicense = '[href=""] > .btn-primary' +const btnUpdateLicense = ':nth-child(1) > .btn' +const txtFullName = '#fullName' +const txtShortName = '#shortName' +const selectLicenseType = '#licenseTypeDatabaseId' +const selectOSIApproved = '#OSIApproved' +const selectFSFFreeLibre = '#FSFLibre' +const cbIsChecked = '#isChecked' +const txtNote = '#note' +const txtLicenseText = '#text' +const tabLicense = '#tab-details' +const tabLinkedObligations = '#tab-obligations' +const tblObligations = '.gridjs' +const dlgLicenseObligations = { + 'sltDialog': '.modal-content', + 'sltTable': '.modal-body > :nth-child(1) > .row > :nth-child(2) > .gridjs', + 'sltCheckbox': '[data-column-id="obligationId"] > div > .checkbox-control', + 'sltAddBtn': '.modal-footer [type="button"]:nth-child(2)' +} +const btnDeleteLicense = ':nth-child(2) > .btn' +const dlgDeleteLicense = { + 'dialog': '.modal-content', + 'btnDeleteLicense': '.login-btn', + 'txtNotification': '.modal-body > .fade' +} +const rowsLinkedObligation = '.gridjs-tbody > .gridjs-tr' +const dlgDeleteLinkedObligation = { + 'dialog': '.modal-content', + 'btnDeleteObligation': '.login-btn' +} + +export const addEditSelectors = { + btnAddObligation, + btnCreateLicense, + btnUpdateLicense, + txtFullName, + txtShortName, + selectLicenseType, + selectOSIApproved, + selectFSFFreeLibre, + cbIsChecked, + txtNote, + txtLicenseText, + tabLicense, + tabLinkedObligations, + tblObligations, + dlgLicenseObligations, + btnDeleteLicense, + dlgDeleteLicense, + rowsLinkedObligation, + dlgDeleteLinkedObligation +} + +//elements of view page +const tblLicenseList = '.gridjs-tbody' +const btnAddLicense = '[href="/licenses/add"] > .btn' +const navLicense = '.navbar-nav [href="/licenses"]' +const externalLink = '[name="externalLicenseLink"]' +const btnSave = '[class^="detail_button-save"]' +const fullName = '.table > tbody > :nth-child(1) > :nth-child(2)' +const shortName = '.table > tbody > :nth-child(2) > :nth-child(2)' +const isChecked = '.badge' +const licenseType = '.table > tbody > :nth-child(4) > :nth-child(2)' +const OSIApproved = ':nth-child(5) > :nth-child(2) > span' +const FSFFreeLibre = ':nth-child(6) > :nth-child(2) > span' +const note = ':nth-child(8) > :nth-child(2)' +const tabText = '#tab-text' +const licenseText = '[class^=detail_pre-text]' +const tabObligations = '#tab-obligations' +const tblLinkedObligations = ':nth-child(4) > .row > :nth-child(1) > :nth-child(2) > .gridjs .gridjs-table .gridjs-tbody' +const btnEditWhiteList = '[href=""] > .btn' +const tblWhiteList = ':nth-child(4) > .row > :nth-child(1) > :nth-child(2) > .gridjs tbody' +const tblUpdateWhiteList = ':nth-child(4) > .row > :nth-child(2) > .gridjs .gridjs-tbody' +const cbWhiteList = '[data-column-id="obligationId"] > :nth-child(1) > div > .form-check-input' +const btnUpdateWhiteList = '.btn-group > :nth-child(1) > .btn' +const alertMessage = '.alert-success' +const btnExportSpreadsheet = '[href="/licenses"] > .btn' + +export const viewSelectors = { + tblLicenseList, + btnAddLicense, + navLicense, + externalLink, + btnSave, + fullName, + shortName, + isChecked, + licenseType, + OSIApproved, + FSFFreeLibre, + note, + tabText, + licenseText, + tabObligations, + tblLinkedObligations, + btnEditWhiteList, + tblWhiteList, + tblUpdateWhiteList, + cbWhiteList, + btnUpdateWhiteList, + alertMessage, + btnExportSpreadsheet +} \ No newline at end of file diff --git a/cypress/e2e/licenses/update.cy.js b/cypress/e2e/licenses/update.cy.js new file mode 100644 index 000000000..683269af9 --- /dev/null +++ b/cypress/e2e/licenses/update.cy.js @@ -0,0 +1,63 @@ +// 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 + +import { addEditSelectors, viewSelectors } from './selectors' +import { registerLicense, fillDataLicense, addObligations, verifyDetailsLicense, deleteLicensesBeforeRegisterUpdate, gotoUpdateLicensePage } from './utils' + +function deleteObligationAndVerify() { + cy.get(addEditSelectors.rowsLinkedObligation).eq(0).as('deletedObligationRow') + cy.get('@deletedObligationRow').should('exist'); + cy.get('@deletedObligationRow').find('td').eq(1).invoke('text').as('deletedObligationText') + cy.get('@deletedObligationRow').find('td').last().find('svg').click(); + cy.get(addEditSelectors.dlgDeleteLinkedObligation.dialog).should('be.visible') + // to do verify message: "Do you really want to delete the obligation @deletedObligationText?" + cy.get(addEditSelectors.dlgDeleteLinkedObligation.btnDeleteObligation).click() + cy.get(addEditSelectors.rowsLinkedObligation).contains('td', '@deletedObligationText').should('not.exist') +} + +function updateLicense(updatedData) { + cy.get(addEditSelectors.txtFullName).should('not.have.value', '') + cy.get(addEditSelectors.txtShortName).should('not.have.value', '') + if (updatedData.license_tab) + fillDataLicense(updatedData.license_tab, true) + if (updatedData.linked_obligations_tab) { + cy.get(addEditSelectors.tabLinkedObligations).click() + if (updatedData.linked_obligations_tab.delete_obligation == true) + deleteObligationAndVerify() + addObligations(updatedData.linked_obligations_tab) + } + cy.get(addEditSelectors.btnUpdateLicense).click() + cy.get(viewSelectors.alertMessage).contains('Success: License updated successfully!') + cy.contains('button', 'Edit License') +} + +describe('Update a license', () => { + + before(() => { + deleteLicensesBeforeRegisterUpdate('licenses/update', true) + cy.login('admin') + cy.fixture('licenses/update').then((license) => { + const initialData = license['TC04_EDIT_SOME_FIELDS'].initial_data + registerLicense(initialData) + }) + }) + + it('TC04: Edit License and remove/ add Obligations', () => { + cy.fixture('licenses/update').then((license) => { + const initialData = license['TC04_EDIT_SOME_FIELDS'].initial_data + const initialLicenseShortName = initialData.license_tab.short_name + const updatedData = license['TC04_EDIT_SOME_FIELDS'].updated_data + // todo search a license by quick filter + gotoUpdateLicensePage(initialLicenseShortName) + updateLicense(updatedData) + verifyDetailsLicense(updatedData) + }) + }) +}) \ No newline at end of file diff --git a/cypress/e2e/licenses/utils.js b/cypress/e2e/licenses/utils.js new file mode 100644 index 000000000..832de5731 --- /dev/null +++ b/cypress/e2e/licenses/utils.js @@ -0,0 +1,183 @@ +// 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 + +import { addEditSelectors, viewSelectors } from './selectors' + +export function goToRegisterLicensePage() { + cy.get(viewSelectors.navLicense).click() + cy.contains('Add License') + cy.get(viewSelectors.btnAddLicense).click() + cy.contains('Create License') +} + +export function addObligations(testData) { + cy.contains('button', addEditSelectors.btnAddObligation).click() + cy.get(addEditSelectors.dlgLicenseObligations.sltDialog).should('be.visible') + cy.contains('Select License Obligations to be added') + cy.get(addEditSelectors.dlgLicenseObligations.sltDialog).within(() => { + let addedObligations = testData.added_obligations + for (let i = 0; i < addedObligations.length; i++) { + cy.selectItemsFromTable(addEditSelectors.dlgLicenseObligations.sltCheckbox, false, addedObligations[i]) + } + cy.get(addEditSelectors.dlgLicenseObligations.sltAddBtn).click() + }) + cy.get(addEditSelectors.dlgLicenseObligations.sltDialog).should('not.exist') + cy.get(addEditSelectors.tblObligations).should('be.visible') +} + +export function fillDataLicense(testData, isUpdate) { + const nStep = Object.keys(testData).length + for (let i = 0; i < nStep; i++) { + const keyFieldName = Object.keys(testData)[i] + const fieldValue = testData[keyFieldName] + switch (keyFieldName) { + case 'full_name': + if (isUpdate == true) + cy.get(addEditSelectors.txtFullName).clearAndType(fieldValue) + else + cy.get(addEditSelectors.txtFullName).type(fieldValue) + break + case 'short_name': + if (isUpdate == true) + cy.get(addEditSelectors.txtShortName).clearAndType(fieldValue) + else + cy.get(addEditSelectors.txtShortName).type(fieldValue) + break + case 'is_checked': + if (fieldValue == true) + cy.get(addEditSelectors.cbIsChecked).check() + else cy.get(addEditSelectors.cbIsChecked).uncheck() + break + case 'license_type_index': + cy.get(addEditSelectors.selectLicenseType).select(fieldValue) + break + case 'OSI_Approved': + cy.get(addEditSelectors.selectOSIApproved).select(fieldValue.value) + break + case 'FSF_Free/Libre': + cy.get(addEditSelectors.selectFSFFreeLibre).select(fieldValue.value) + break + case 'note': + if (isUpdate == true) + cy.get(addEditSelectors.txtNote).clearAndType(fieldValue) + else + cy.get(addEditSelectors.txtNote).type(fieldValue) + break + case 'license_text': + if (isUpdate == true) + cy.get(addEditSelectors.txtLicenseText).clearAndType(fieldValue) + else + cy.get(addEditSelectors.txtLicenseText).type(fieldValue) + break + default: + break + } + } +} + +function verifyDetailsTab(expectedOutput) { + const nStep = Object.keys(expectedOutput).length + for (let i = 0; i < nStep; i++) { + const keyFieldName = Object.keys(expectedOutput)[i] + const fieldValue = expectedOutput[keyFieldName] + switch (keyFieldName) { + case 'full_name': + cy.get(viewSelectors.fullName).should('contain', fieldValue) + break + case 'short_name': + cy.get(viewSelectors.shortName).should('contain', fieldValue) + break + case 'is_checked': + if (fieldValue == true) + cy.get(viewSelectors.isChecked).should('contain', 'CHECKED') + else + cy.get(viewSelectors.isChecked).should('contain', 'UNCHECKED') + break + case 'license_type_index': + cy.get(viewSelectors.licenseType).should('not.be.empty') + break + case 'OSI_Approved': + cy.get(viewSelectors.OSIApproved).invoke('text').should('contain', fieldValue.name) + break + case 'FSF_Free/Libre': + cy.get(viewSelectors.FSFFreeLibre).should('contain', fieldValue.name) + break + case 'note': + cy.get(viewSelectors.note).should('contain', fieldValue) + break + default: + break + } + } +} + +function verifyTextTab(expectedOutput) { + if (expectedOutput) cy.get(viewSelectors.licenseText).should('contain', expectedOutput) + else cy.get(viewSelectors.licenseText).should('contain', '') +} + +function verifyObligationsTab(expectedOutput) { + // todo fix bug display obligation in list + // cy.get(viewSelectors.tblLinkedObligations).as('tableBody') + // cy.get('@tableBody').find('tr').should('have.length', expectedOutput.added_obligation_quantity) +} + +export function verifyDetailsLicense(expectedOutput) { + const outputDetails = expectedOutput.license_tab + const outputLicenseText = expectedOutput.license_tab.license_text + const outputLinkedObligation = expectedOutput.linked_obligations_tab + verifyDetailsTab(outputDetails) + if (outputLicenseText) { + cy.get(viewSelectors.tabText).click() + verifyTextTab(outputLicenseText) + } + if (outputLinkedObligation) { + cy.get(viewSelectors.tabObligations).click() + verifyObligationsTab(outputLinkedObligation) + } +} + +export function registerLicense(testData) { + goToRegisterLicensePage() + if (testData.license_tab) + fillDataLicense(testData.license_tab, false) + if (testData.linked_obligations_tab) { + cy.get(addEditSelectors.tabLinkedObligations).click() + addObligations(testData.linked_obligations_tab) + } + cy.get(addEditSelectors.btnCreateLicense).click() + cy.get(viewSelectors.alertMessage).contains('Success: License added successfully!') + cy.contains('Add License') +} + +export function deleteLicensesBeforeRegisterUpdate(filePath, isUpdate) { + cy.fixture(filePath).then((testIds) => { + const testIdsNum = Object.keys(testIds).length + for (let i = 0; i < testIdsNum; i++) { + let shortName + const keyTestId = Object.keys(testIds)[i] + const fieldValue = testIds[keyTestId] + if (isUpdate) { + shortName = fieldValue.initial_data.license_tab.short_name + } else { + shortName = fieldValue.license_tab.short_name + } + cy.deleteLicense(shortName) + } + }) +} + +export function gotoUpdateLicensePage(licenseShortName) { + cy.get(viewSelectors.navLicense).click() + cy.contains('Add License') + cy.contains('a', licenseShortName).click() + cy.get('a > .btn').click() + cy.contains('Update License') +} diff --git a/cypress/fixtures/licenses/delete.json b/cypress/fixtures/licenses/delete.json new file mode 100644 index 000000000..16f69cf09 --- /dev/null +++ b/cypress/fixtures/licenses/delete.json @@ -0,0 +1,6 @@ +{ + "TC05_DELETE_LICENSE": { + "full_name": "Apache License", + "short_name": "Apache-2.0" + } +} \ No newline at end of file diff --git a/cypress/fixtures/licenses/register.json b/cypress/fixtures/licenses/register.json new file mode 100644 index 000000000..c9c0e9cc9 --- /dev/null +++ b/cypress/fixtures/licenses/register.json @@ -0,0 +1,42 @@ +{ + "TC01_REQUIRED_FIELDS": { + "license_tab": { + "full_name": "Open Logistics Foundation License v1.3", + "short_name": "OLFL-1.3" + }, + "external_link": "https://eclipse.dev/sw360/docs/development/testcases/test-cases-licenses/" + }, + + "TC02_ALL_FIELDS": { + "license_tab": { + "full_name": "JAM License", + "short_name": "Jam", + "license_type_index": 1, + "OSI_Approved": { + "name": "Yes", + "value": "YES" + }, + "FSF_Free/Libre": { + "name": "(n/a)", + "value": "NA" + }, + "is_checked": false, + "note": "take a note!", + "license_text": "Copyright (C) YEAR by AUTHOR EMAIL Permission to use, copy and modify." + }, + "linked_obligations_tab": { + "added_obligations": [0, 1] + } + }, + + "TC03_LINKED_OBLIGATION": { + "license_tab": { + "full_name": "Apache License 2.1", + "short_name": "Apache-2.1" + }, + "linked_obligations_tab": { + "added_obligations": [0, 1, 3] + }, + "update_white_list": [false, true, true] + } +} \ No newline at end of file diff --git a/cypress/fixtures/licenses/update.json b/cypress/fixtures/licenses/update.json new file mode 100644 index 000000000..0aa16e97b --- /dev/null +++ b/cypress/fixtures/licenses/update.json @@ -0,0 +1,32 @@ +{ + "TC04_EDIT_SOME_FIELDS": { + "initial_data": { + "license_tab": { + "full_name": "PHP License", + "short_name": "PHP-3.01", + "license_text": "Copyright (C) YEAR by AUTHOR EMAIL Permission to use, copy and modify." + }, + "linked_obligations_tab": { + "added_obligations": [0, 1] + } + }, + "updated_data": { + "license_tab": { + "full_name": "PHP License 3.01", + "OSI_Approved": { + "name": "(n/a)", + "value": "NA" + }, + "FSF_Free/Libre": { + "name": "Yes", + "value": "YES" + }, + "license_text": " " + }, + "linked_obligations_tab": { + "delete_obligation": true, + "added_obligations": [2, 3] + } + } + } +} \ No newline at end of file diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 29c9d8cc6..029ad20f9 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -232,12 +232,16 @@ Cypress.Commands.add('createLicense', (licenseShortName) => { cy.exec('bash cypress/support/common.sh createLicense ' + licenseShortName) }) +Cypress.Commands.add('createLicenseType', (licenseType) => { + cy.exec('bash cypress/support/common.sh createLicenseType ' + licenseType) +}) + Cypress.Commands.add('deleteLicense', (licenseShortName) => { cy.exec('bash cypress/support/common.sh deleteLicenseByShortName ' + licenseShortName) }) Cypress.Commands.overwrite('type', (originalFn, element, text, options) => { - return originalFn(element, text, { ...options, delay: 0 } ) + return originalFn(element, text, { ...options, delay: 0 }) }) Cypress.Commands.add('selectOneUser', (dialogSelectors, userNo) => { @@ -264,4 +268,44 @@ Cypress.Commands.add('selectMultiUsers', (dialogSelectors, numUser) => { cy.get(dialogSelectors.selectUsersBtn) .click() +}) + +Cypress.Commands.add( + 'clearAndType', + { + prevSubject: true, + }, + (subject, text) => cy.wrap(subject).type(`{selectall}{backspace}${text}`), +) + +Cypress.Commands.add('createLicenseByAPI', (fullName, shortName) => { + cy.task('generateApiToken').then((token) => { + const myHeaders = createRequestHeader(token) + const raw = JSON.stringify({ + "fullName": fullName, + "shortName": shortName + }) + + const requestOptions = { + method: 'POST', + headers: myHeaders, + body: raw, + } + + fetch(`${Cypress.env('sw360_api_server')}/resource/api/licenses`, requestOptions) + }) +}) + +Cypress.Commands.add('downloadFile', (downloadButtonSelector) => { + cy.get(downloadButtonSelector).click() +}) + +Cypress.Commands.add('verifyDownloadedFile', (fileName) => { + cy.readFile('cypress/downloads/' + fileName).should('exist') +}) + +Cypress.Commands.add('removeDownloadsFolder', () => { + cy.task('removeDownloadsFolder').then(() => { + cy.log('Downloads folder is removed successfully') + }) }) \ No newline at end of file diff --git a/cypress/support/common.sh b/cypress/support/common.sh index 4873ebb79..4e01395f6 100755 --- a/cypress/support/common.sh +++ b/cypress/support/common.sh @@ -172,6 +172,69 @@ delete_oauth_client() { }" | jq -r '.docs[] | "curl -X DELETE 'http://$COUCHDB_USERNAME:$COUCHDB_PASSWORD@$COUCHDB_IP:$COUCHDB_PORT'/'$OAUTH_DB_NAME'/" + ._id + "?rev=" + ._rev' | sh } +create_license_type() { + licensetype="$1" + JSON_DATA=" + { + \"type\": \"licenseType\", + \"licenseType\": \"$licensetype\", + \"issetBitfield\": \"1\" + } + " + curl -X POST "http://$COUCHDB_USERNAME:$COUCHDB_PASSWORD@$COUCHDB_IP:$COUCHDB_PORT/$DB_NAME" \ + -H "Content-Type: application/json" \ + -d "$JSON_DATA" +} + +delete_all_license_types() { + curl -X POST "http://$COUCHDB_USERNAME:$COUCHDB_PASSWORD@$COUCHDB_IP:$COUCHDB_PORT/$DB_NAME/_find" -H "Content-Type: application/json" -d '{ + "selector": { + "type": "licenseType" + }, + "fields": ["_id", "_rev"], + "limit": 100 + }' | jq -r '.docs[] | "curl -X DELETE 'http://$COUCHDB_USERNAME:$COUCHDB_PASSWORD@$COUCHDB_IP:$COUCHDB_PORT'/'$DB_NAME'/" + ._id + "?rev=" + ._rev' | sh +} + +create_obligation() { + title="$1" + text="$2" + obligationLevel="$3" + case $3 in + 1) obligationLevel="ORGANISATION_OBLIGATION";; + 2) obligationLevel="COMPONENT_OBLIGATION";; + 3) obligationLevel="PROJECT_OBLIGATION";; + 4) obligationLevel="LICENSE_OBLIGATION";; + *) echo "Invalid obligation level"; exit 1;; + esac + JSON_DATA=$(cat < { console.error('Uncaught exception occurred:', err); return false; -}) \ No newline at end of file +}) diff --git a/cypress/support/tasks.ts b/cypress/support/tasks.ts index 29eeac7bc..bcc51a4ef 100644 --- a/cypress/support/tasks.ts +++ b/cypress/support/tasks.ts @@ -62,8 +62,10 @@ const cleanDB = () => { runShellCommand('bash cypress/support/common.sh deleteAllComponents'), runShellCommand('bash cypress/support/common.sh deleteAllProjects'), runShellCommand('bash cypress/support/common.sh deleteAllLicenses'), + runShellCommand('bash cypress/support/common.sh deleteAllLicenseTypes'), runShellCommand('bash cypress/support/common.sh deleteAllVendors'), - ...clearUserByEmail() + ...clearUserByEmail(), + runShellCommand('bash cypress/support/common.sh deleteAllObligations') ] return Promise.all(bashs) } @@ -74,6 +76,31 @@ const initData = () => { const licenseNames = ['AAL-1.01', 'Abstyles-2024', 'AFL-4.5'] const bashs = [] + const licenseTypes = ['LicenseType01', 'LicenseType02', 'LicenseType03'] + + const obligations = [ + { + 'title': '"obligation 001"', + 'text': '"This is obligation text 001"', + 'obligationLevel': 4 + }, + { + 'title': '"obligation 002"', + 'text': '"This is obligation text 002"', + 'obligationLevel': 4 + }, + { + 'title': '"obligation 003"', + 'text': '"This is obligation text 003"', + 'obligationLevel': 4 + }, + { + 'title': '"obligation 004"', + 'text': '"This is obligation text 004"', + 'obligationLevel': 4 + } + ] + for (const vendorName of vendorNames) { bashs.push(runShellCommand(`bash cypress/support/common.sh createVendor ${vendorName}`)) @@ -83,30 +110,36 @@ const initData = () => { bashs.push(runShellCommand(`bash cypress/support/common.sh createLicense ${licenseName}`)) } + for (const licenseType of licenseTypes) { + bashs.push(runShellCommand(`bash cypress/support/common.sh createLicenseType ${licenseType}`)) + } + for (const user of users) { bashs.push(runShellCommand(`bash cypress/support/common.sh createUser ${user.email} ${user.givename} ${user.lastname} ${user.usergroup}`)) } + for (const obligation of obligations) { + bashs.push(runShellCommand(`bash cypress/support/common.sh createObligation ${obligation.title} ${obligation.text} ${obligation.obligationLevel}`)) + } + return Promise.all(bashs) } module.exports = (on: any, config: any) => { on('task', { - removeDownloadedFiles() { - const downloadPath = 'cypress/downloads' + removeDownloadsFolder() { + const folderName = 'cypress/downloads' + const { rmdir } = require('fs') + console.log('deleting folder %s', folderName); return new Promise((resolve, reject) => { - fs.readdir(downloadPath, (err, files) => { + rmdir(folderName, { maxRetries: 10, recursive: true }, (err: any) => { if (err) { - reject(err); - } else { - files.forEach((file) => { - const filePath = `${downloadPath}/${file}`; - fs.unlinkSync(filePath); - }); - resolve(true); + console.error(err); + return reject(err); } + resolve(null); }); - }) + }); }, async generateApiToken() { const users = JSON.parse(fs.readFileSync('cypress/fixtures/sw360_users.json', 'utf-8'))