diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml index 344103b..9c104ad 100644 --- a/.gitea/workflows/release.yaml +++ b/.gitea/workflows/release.yaml @@ -136,7 +136,7 @@ jobs: replace-in-files --regex='"hosturl".*' --replacement='hosturl:"http://localhost:4200",' ./cypress.config.ts cat ./cypress.config.ts # Start frontend and run cypress - npm start & npx wait-on http://localhost:4200 && npx cypress run --browser chrome --spec "cypress/e2e/liveness.cy.ts,cypress/e2e/editor.cy.ts,cypress/e2e/excel.cy.ts,cypress/e2e/filtering.cy.ts,cypress/e2e/licensing.cy.ts" + npm start & npx wait-on http://localhost:4200 && npx cypress run --browser chrome --spec "cypress/e2e/liveness.cy.ts,cypress/e2e/editor.cy.ts,cypress/e2e/excel-multi-load.cy.ts,cypress/e2e/excel.cy.ts,cypress/e2e/filtering.cy.ts,cypress/e2e/licensing.cy.ts" - name: Zip Cypress videos if: always() diff --git a/client/cypress/e2e/excel-multi-load.cy.ts b/client/cypress/e2e/excel-multi-load.cy.ts new file mode 100644 index 0000000..6a9d03c --- /dev/null +++ b/client/cypress/e2e/excel-multi-load.cy.ts @@ -0,0 +1,224 @@ +import { Callbacks } from 'cypress/types/jquery/index' + +const username = Cypress.env('username') +const password = Cypress.env('password') +const hostUrl = Cypress.env('hosturl') +const appLocation = Cypress.env('appLocation') +const longerCommandTimeout = Cypress.env('longerCommandTimeout') +const serverType = Cypress.env('serverType') +const libraryToOpenIncludes = Cypress.env(`libraryToOpenIncludes_${serverType}`) +const fixturePath = 'excels_multi_load/' + +context('excel multi load tests: ', function () { + this.beforeAll(() => { + cy.visit(`${hostUrl}/SASLogon/logout`) + cy.loginAndUpdateValidKey(true) + }) + + this.beforeEach(() => { + cy.visit(hostUrl + appLocation) + // cy.get('input.username').type(username) + // cy.get('input.password').type(password) + // cy.get('.login-group button').click() + + visitPage('home/multi-load') + + colorLog( + `TEST START ---> ${ + Cypress.mocha.getRunner().suite.ctx.currentTest.title + }`, + '#3498DB' + ) + }) + + it('1 | Uploads Excel file with multiple sheets, 3 sheets including data, 2 sheets matched with dataset', (done) => { + attachExcelFile('multi_load_test_2.xlsx', () => { + checkHotUserDatasetTable('hotTableUserDataset', [ + ['DC996664', 'MPE_X_TEST'], + ['DC996664', 'MPE_TABLES'] + ], () => { + cy.get('#continue-btn').trigger('click').then(() => { + checkIfTreeHasTables(['DC996664.MPE_X_TEST', 'DC996664.MPE_TABLES'], undefined, (includes: boolean) => { + if (includes) { + // MPE_TABLES sheet does not have data so 1 error image must be shown + hasErrorTables(1, (valid: boolean) => { + if (valid) done() + }) + } + }) + }) + }) + }) + }) + + it('2 | Uploads Excel file with multiple sheets, 2 sheets matched with dataset, 1 matched sheet does not have data', (done) => { + attachExcelFile('multi_load_test_1.xlsx', () => { + checkHotUserDatasetTable('hotTableUserDataset', [ + ['DC996664', 'MPE_X_TEST'], + ['DC996664', 'MPE_TABLES'] + ], () => { + cy.get('#continue-btn').trigger('click').then(() => { + checkIfTreeHasTables(['DC996664.MPE_X_TEST', 'DC996664.MPE_TABLES'], 'DC996664.MPE_X_TEST', (includes: boolean) => { + if (includes) { + cy.get('#hotTable').should('be.visible').then(() => { + checkHotUserDatasetTable('hotTable', [ + ['No', '1', 'more dummy data'], + ['No', '1', 'It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told:'], + ['No', '1', 'if you can fill the unforgiving minute'] + ], () => { + submitTables() + + hasSuccessSubmits(2, (valid: boolean) => { + if (valid) done() + }) + + }) + }) + } + }) + }) + }) + }) + }) + + it('3 | Uploads Excel file with multiple sheets, 1 sheets has 2 tables', (done) => { + attachExcelFile('multi_load_test_1.xlsx', () => { + checkHotUserDatasetTable('hotTableUserDataset', [ + ['DC996664', 'MPE_X_TEST'], + ['DC996664', 'MPE_TABLES'] + ], () => { + cy.get('#continue-btn').trigger('click').then(() => { + checkIfTreeHasTables(['DC996664.MPE_X_TEST', 'DC996664.MPE_TABLES'], 'DC996664.MPE_X_TEST', (includes: boolean) => { + if (includes) { + cy.get('#hotTable').should('be.visible').then(() => { + checkHotUserDatasetTable('hotTable', [ + ['No', '1', 'more dummy data'], + ['No', '1', 'It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told:'], + ['No', '1', 'if you can fill the unforgiving minute'] + ], () => { + clickOnTreeNode('DC996664.MPE_TABLES', () => { + cy.wait(1000).then(() => { + cy.get('#hotTable').should('be.visible').then(() => { + checkHotUserDatasetTable('hotTable', [ + ['No', 'DC914286', 'MPE_COLUMN_LEVEL_SECURITY'], + ['No', 'DC914286', 'MPE_XLMAP_INFO'], + ['No', 'DC914286', 'MPE_XLMAP_RULES'] + ], () => { + submitTables() + + hasSuccessSubmits(2, (valid: boolean) => { + if (valid) done() + }) + + }) + }) + }) + }) + }) + }) + } + }) + }) + }) + }) + }) + + this.afterEach(() => { + colorLog(`TEST END -------------`, '#3498DB') + // cy.visit(`${hostUrl}/SASLogon/logout`) + }) +}) + +const attachExcelFile = (excelFilename: string, callback?: any) => { + cy.get('#browse-file') + .should('exist') + .click() + .then(() => { + cy.get('input[type="file"]#file-upload') + .attachFile(`/${fixturePath}/${excelFilename}`) + .then(() => { + if (callback) callback() + }) + }) +} + +const checkHotUserDatasetTable = (hotId: string, dataToContain: any[][], callback?: () => void) => { + cy.get(`#${hotId}`, { timeout: longerCommandTimeout }) + .find('div.ht_master.handsontable') + .find('div.wtHolder') + .find('div.wtHider') + .find('div.wtSpreader') + .find('table.htCore') + .find('tbody') + .then((data) => { + cy.wait(2000).then(() => { + for (let rowI = 0; rowI < dataToContain.length; rowI++) { + for (let colI = 0; colI < dataToContain[rowI].length; colI++) { + expect(data[0].children[rowI].children[colI]).to.contain(dataToContain[rowI][colI]) + } + } + + if (callback) callback() + }) + }) +} + +const clickOnTreeNode = (clickOnNode: string, callback?: () => void) => { + cy.get('.nav-tree clr-tree > clr-tree-node').then((treeNodes: any) => { + for (let node of treeNodes) { + if (node.innerText.toUpperCase().trim().includes(clickOnNode)) { + cy.get(node).trigger('click') + if (callback) callback() + } + } + }) +} + +const checkIfTreeHasTables = (tables: string[], clickOnNode?: string, callback?: (includes: boolean) => void) => { + cy.get('.nav-tree clr-tree > clr-tree-node').then((treeNodes: any) => { + let datasets = tables + let nodesCorrect = true + let nodeToClick + + for (let node of treeNodes) { + if (!datasets.includes(node.innerText.toUpperCase().trim())) { + nodesCorrect = false + } + + if (clickOnNode) { + if (node.innerText.toUpperCase().trim().includes(clickOnNode)) { + nodeToClick = node + } + } + } + + if (nodeToClick) cy.get(nodeToClick).trigger('click') + + if (callback) callback(nodesCorrect) + }) +} + +const submitTables = () => { + cy.get('#submit-all').trigger('click') + cy.get('#submit-tables').trigger('click') +} + +const hasSuccessSubmits = (expectedNoOfSubmits: number, callback: (valid: boolean) => void) => { + cy.get('.nav-tree clr-tree > clr-tree-node cds-icon[status="success"]').should('be.visible').then(($nodes) => { + callback(expectedNoOfSubmits === $nodes.length) + }) +} + +const hasErrorTables = (expectedNoOfErrors: number, callback: (valid: boolean) => void) => { + cy.get('.nav-tree clr-tree > clr-tree-node cds-icon[status="danger"]').should('be.visible').then(($nodes) => { + callback(expectedNoOfErrors === $nodes.length) + }) +} + +const visitPage = (url: string) => { + cy.visit(`${hostUrl}${appLocation}/#/${url}`) +} + +const colorLog = (msg: string, color: string) => { + console.log('%c' + msg, 'color:' + color + ';font-weight:bold;') +} diff --git a/client/cypress/fixtures/excels_multi_load/multi_load_test_1.xlsx b/client/cypress/fixtures/excels_multi_load/multi_load_test_1.xlsx new file mode 100644 index 0000000..484d591 Binary files /dev/null and b/client/cypress/fixtures/excels_multi_load/multi_load_test_1.xlsx differ diff --git a/client/cypress/fixtures/excels_multi_load/multi_load_test_2.xlsx b/client/cypress/fixtures/excels_multi_load/multi_load_test_2.xlsx new file mode 100644 index 0000000..44b96e5 Binary files /dev/null and b/client/cypress/fixtures/excels_multi_load/multi_load_test_2.xlsx differ diff --git a/client/cypress/fixtures/excels_multi_load/multi_load_test_3.xlsx b/client/cypress/fixtures/excels_multi_load/multi_load_test_3.xlsx new file mode 100644 index 0000000..5e21552 Binary files /dev/null and b/client/cypress/fixtures/excels_multi_load/multi_load_test_3.xlsx differ diff --git a/client/src/app/editor/editor.component.ts b/client/src/app/editor/editor.component.ts index 704e6c8..ff098fa 100644 --- a/client/src/app/editor/editor.component.ts +++ b/client/src/app/editor/editor.component.ts @@ -512,7 +512,7 @@ export class EditorComponent implements OnInit, AfterViewInit { } }) .catch((error: string) => { - this.eventService.showInfoModal('Error', error) + this.eventService.showAbortModal(null, error, null) this.showUploadModal = false this.uploadPreview = false diff --git a/client/src/app/multi-dataset/multi-dataset.component.html b/client/src/app/multi-dataset/multi-dataset.component.html index f93e60b..fce8e4f 100644 --- a/client/src/app/multi-dataset/multi-dataset.component.html +++ b/client/src/app/multi-dataset/multi-dataset.component.html @@ -6,6 +6,7 @@
-
@@ -147,6 +148,7 @@