diff --git a/.gitignore b/.gitignore index 2277ae7a..c2c5154b 100644 --- a/.gitignore +++ b/.gitignore @@ -110,5 +110,5 @@ sw.* # Certifact files .certs/ -cypress/videos -cypress/downloads \ No newline at end of file +test/cypress/videos +test/cypress/downloads diff --git a/cypress.config.js b/cypress.config.js index e8f8d6b5..4b0e281d 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -9,6 +9,8 @@ module.exports = defineConfig({ baseUrl: process.env.ROOT_URL ? process.env.ROOT_URL : 'http://localhost:3000', experimentalStudio: true, projectId: process.env.CYPRESS_PROJECT_ID, + specPattern: "test/cypress/e2e/**/*.cy.{js,jsx,ts,tsx}", + supportFile: "test/cypress/support/e2e.js", viewportWidth: 1600, viewportHeight: 900, //Prevent huge amount of time on reloading page @@ -18,4 +20,8 @@ module.exports = defineConfig({ // implement node event listeners here }, }, + fixturesFolder: "test/cypress/fixtures", + screenshotsFolder: "test/cypress/screenshots", + videosFolder: "test/cypress/videos", + downloadsFolder: "test/cypress/downloads", }); diff --git a/package.json b/package.json index 7d0719a0..07b8eab5 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "generate-icons": "vsvg -s ./static/icons-svg -t ./static/icons-js", "test": "jest", "test:debug": "node --inspect node_modules/.bin/jest --runInBand", - "test-run-e2e": "cypress run --record" + "test-run-e2e": "cypress run" }, "dependencies": { "@abi-software/gallery": "0.3.2", diff --git a/test/cypress/e2e/datasets.cy.js b/test/cypress/e2e/datasets.cy.js new file mode 100644 index 00000000..db8575f8 --- /dev/null +++ b/test/cypress/e2e/datasets.cy.js @@ -0,0 +1,186 @@ +const datasetIds = [127]; + + +datasetIds.forEach(datasetId => { + + describe(`Dataset ${datasetId}`, {testIsolation: false }, function () { + before(function () { + cy.visit(`/datasets/${datasetId}?type=dataset`) + }); + + it("Landing page", function () { + cy.get('.dataset-image').should('have.attr', 'src').and('include', 'https://assets.discover.pennsieve.io/') + // Hover over author + cy.get(':nth-child(2) > .contributor-item').should('be.visible').trigger('mouseenter', { eventConstructor: 'MouseEvent' }) + + //only one visible popover + cy.get('.orcid-popover:visible').should('have.length', 1) + + //Check Get Dataset directs to files tab + cy.contains('.button-container span', 'Get Dataset').click() + cy.get('.nuxt-link-exact-active').should('have.text', ' Files '); + cy.get('[style=""] > .heading2.mb-8').should('have.text', 'Download Dataset').and('be.visible') + //Checkt Cite Dataset direccts to Cite tab + cy.contains('.button-container span', 'Cite Dataset').click() + cy.get('.nuxt-link-exact-active').should('have.text', ' Cite '); + cy.get('.citation-details > .heading2').should('have.text', '\n Dataset Citation\n ').and('be.visible') + cy.get('.dataset-information-box > :nth-child(2) > a').should('have.attr', 'href').and('include', 'doi.org').then((href) => { + cy.request(href).then((resp) => { + expect(resp.status).to.eq(200); + expect(resp.body).to.include(`datasets/${datasetId}/version`); + }) + }); + cy.get(':nth-child(2) > .contributor-list > li > .el-tooltip > .tooltip-item > a').each($el => { + cy.wrap($el).should('have.attr', 'href').and('include', '/data?type='); + }); + cy.get('.dataset-information-box > div').contains('View other versions').click(); + //Check if each link + cy.get('.el-col-push-1 > a').each(($link) => { + cy.wrap($link).should('have.attr', 'href').and('include', 'doi.org').then((href) => { + cy.request(href).then((resp) => { + cy.request(href).its('body').should('include', `/datasets/${datasetId}/version`); + }); + }); + }) + }); + it("Abstract Tab", function () { + cy.contains('#datasetDetailsTabsContainer .style1', ' Abstract ').click(); + cy.get('.nuxt-link-exact-active').should('have.text', ' Abstract '); + cy.get('.dataset-description-info > :nth-child(1) > :nth-child(1) > strong').contains('Study Purpose'); + cy.get('.dataset-description-info > :nth-child(1) > :nth-child(2) > strong').contains('Data Collection'); + cy.get('.dataset-description-info > :nth-child(1) > :nth-child(3) > strong').contains('Primary Conclusion'); + cy.get('.experimental-design-section-text-column').contains('Protocol Links'); + //cy.get('.experimental-design-container .link2').should('have.attr', 'href').and('include', 'https://doi.org/') + //The following regular expression should capture space and letters + cy.get('.dataset-description-info').contains(/Experimental Approach: *(.+)/); + cy.get('.dataset-description-info').contains('Subject Information:'); + cy.get('.dataset-description-info').contains(/Anatomical structure: *(.+)/); + cy.get('.dataset-description-info').contains(/Species: *(.+)/); + cy.get('.dataset-description-info').contains(/Sex: *(.+)/); + cy.get('.dataset-description-info').contains(/Number of samples: *(.+)/); + cy.get('.dataset-description-info').contains(/Keywords: *(.+)/); + cy.contains('.dataset-description-info a', 'Download Metadata file').should('have.attr', 'href').and('include', 'metadata').then((href) => { + cy.request(href).then((resp) => { + expect(resp.status).to.eq(200) + }) + }) + }); + it("About Tab", function () { + cy.contains('#datasetDetailsTabsContainer .style1', ' About ').click(); + cy.get('.nuxt-link-exact-active').should('have.text', ' About '); + cy.get('.dataset-about-info').contains(/Title: *(.+)/); + cy.get('.dataset-about-info').contains(/First Published: *(.+)/); + cy.get('.dataset-about-info').contains(/Last Published: *(.+)/); + cy.get('.dataset-about-info').contains(/Contact Author: *(.+)/); + cy.get('.dataset-about-info').contains(/Award[(]s[)]: (.+)/); + cy.get('.dataset-about-info').contains(/Funding Program[(]s[)]: *(.+)/); + cy.get('.dataset-about-info').contains(/Associated project[(]s[)]: *(.+)/); + cy.get('.dataset-about-info').contains(/Institution[(]s[)]: *(.+)/); + cy.get('.dataset-about-info').contains(/Associated project[(]s[)]: *(.+)/); + cy.get('.dataset-about-info').contains(/Version (.+) Revision (.+): *(.+)/); + cy.get('.dataset-about-info').contains(/Dataset DOI: *(.+)/); + cy.get('.about-section-container > :nth-child(2) > :nth-child(2) > a').should('have.attr', 'href').and('include', 'mailto'); + //Match award link to associated project + cy.get(':nth-child(11) > :nth-child(2) > a').invoke('attr', 'href').then(value => { + cy.get(':nth-child(8) > :nth-child(2) > a').should('have.attr', 'href', value); + }); + //match author to contributors + cy.get('.about-section-container > :nth-child(2) > :nth-child(1)').invoke('text').then(value => { + cy.get('.similar-datasets-container').contains(value); + }) + }); + it("Cite Tab", function () { + cy.contains('#datasetDetailsTabsContainer .style1', ' Cite ').click(); + cy.get('.nuxt-link-exact-active').should('have.text', ' Cite '); + cy.get('.dataset-information-box > :nth-child(2) > a > u').invoke('text').then(value => { + const expectedLink = 'https://citation.crosscite.org/?doi=' + value; + cy.get('.citation-details > p > a').should('have.attr', 'href', expectedLink); + }) + }); + it("Files Tab", function () { + //First check if there is a Files tab + cy.get('#datasetDetailsTabsContainer .style1').then(($tab) => { + if ($tab.text().includes(' Files ')) { + cy.contains('#datasetDetailsTabsContainer .style1', ' Files ').click(); + cy.get('.nuxt-link-exact-active').should('have.text', ' Files '); + cy.get('[style=""] > .heading2.mb-8').should('have.text', 'Download Dataset'); + cy.get('.left-column > :nth-child(1) > div > .label4').should('have.text', 'Option 1 - Direct download: '); + cy.get('.aws-download-column > :nth-child(1) > .label4').should('have.text', 'Option 2 - AWS download: '); + //cy.get('.left-column > :nth-child(1) > a > .el-button > span').should('be.visible'); + cy.get('.left-column .el-button').contains('Download full dataset').should('be.visible'); + //cy.get('.left-column > :nth-child(1) > a > .el-button').should('be.enabled'); + //Find the download file button + cy.contains('.content .body1 .el-table__fixed-body-wrapper .el-table__row', ' dataset_description.xlsx ').should('have.length', 1).as('datasetDescription'); + cy.get('@datasetDescription').find('.el-table_1_column_5').should('have.length', 1).as('icons'); + cy.get('@icons').find('form[id=zipForm]').should('have.length', 1); + //there should be 4 icons, one for each action + cy.get('@icons').find('svg').should('have.length', 4); + //Check get share links + cy.get('@icons').find(':nth-child(4)').click({force: true}); + cy.get('.el-message').should('be.visible'); + //Check oSPARC link + cy.get('@icons').find(':nth-child(3) > .el-tooltip > .svg-icon').click({force: true}); + cy.get('.files-table-table .el-dialog .svg-icon').click(); + } else { + this.skip(); + } + }); + }); + it("Gallery Tab", function () { + cy.contains('#datasetDetailsTabsContainer .style1', ' Gallery ').click(); + cy.get('.content > .full-size').then(($content) => { + //The following call may fail if the wait() is not implemented here + cy.wait(500); + const gallery = $content.find('.gallery-container'); + if (gallery && gallery.length) { + cy.wrap(gallery).find('.sparc-design-system-pagination').as('pagination'); + cy.get('@pagination').find('li.number').should('have.length.least', 1); + cy.wrap(gallery).find('.el-card').should('have.length.least', 1).each($card => { + cy.wrap($card).contains('span', ' View '); + //Need to test newly opened viewers + }); + } else { + cy.wrap($content).contains(' This dataset does not contain gallery items '); + } + }); + }); + it("References Tab", function () { + //First check if reference tab is present + cy.get('#datasetDetailsTabsContainer .style1').then(($tab) => { + if ($tab.text().includes(' References ')) { + cy.contains('#datasetDetailsTabsContainer .style1', ' References ').click(); + cy.get('.nuxt-link-exact-active').should('have.text', ' References '); + cy.get('.dataset-references .heading2').contains('Associated Publications for this Dataset'); + cy.get('.dataset-references .citation-container').each(el => { + cy.wrap(el).find('div > a').should('have.attr', 'href').and('include', 'doi.org'); + cy.wrap(el).find('.copy-button').click(); + cy.get('.el-message').should('be.visible'); + }); + } else { + this.skip(); + } + }); + }); + it("Versions Tab", function () { + //First check if version tab is present + cy.get('#datasetDetailsTabsContainer .style1').then(($tab) => { + if ($tab.text().includes(' Versions ')) { + cy.contains('#datasetDetailsTabsContainer .style1', ' Versions ').click(); + cy.get('.nuxt-link-exact-active').should('have.text', ' Versions '); + cy.get('.table-rows .el-col-push-1 > a').each($el => { + cy.wrap($el).should('have.attr', 'href').and('include', 'doi.org').then((href) => { + cy.request(href).its('body').should('include', `/datasets/${datasetId}/version`); + }) + }); + } + }); + }); + it("Landing page project page", function () { + cy.get('.mt-8 > a > u').click() + cy.get('.subpage').click() + cy.get('.heading2').should('be.visible') + cy.url().should('include', '/projects/') + }); + }); + +}); \ No newline at end of file diff --git a/test/cypress/e2e/finddata.cy.js b/test/cypress/e2e/finddata.cy.js new file mode 100644 index 00000000..72b0ce10 --- /dev/null +++ b/test/cypress/e2e/finddata.cy.js @@ -0,0 +1,9 @@ +describe('Find Data page', () => { + it('Go to dataset', () => { + cy.visit('') + cy.get('.mobile-navigation > :nth-child(1) > :nth-child(1) > a').click() + cy.url().should('include', '/data?type=dataset') + cy.get(':nth-child(1) > .el-table_1_column_2 > .cell > :nth-child(1) > a').click() + cy.url().should('include', '/datasets/') + }) +}) diff --git a/test/cypress/e2e/homepage.cy.js b/test/cypress/e2e/homepage.cy.js new file mode 100644 index 00000000..c4c1c4c3 --- /dev/null +++ b/test/cypress/e2e/homepage.cy.js @@ -0,0 +1,11 @@ +describe('Homepage', () => { + beforeEach(function () { + cy.visit('') + }); + it('Banner', () => { + cy.get('h1').should('contain', 'SPARC') + }) + it('Navigation Bar', () => { + cy.get('.mobile-navigation > :nth-child(1) > :nth-child(1) > a').should('contain', 'Data') + }) +}) diff --git a/test/cypress/fixtures/example.json b/test/cypress/fixtures/example.json new file mode 100644 index 00000000..02e42543 --- /dev/null +++ b/test/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js new file mode 100644 index 00000000..698b01a4 --- /dev/null +++ b/test/cypress/support/commands.js @@ -0,0 +1,37 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } \ No newline at end of file diff --git a/test/cypress/support/e2e.js b/test/cypress/support/e2e.js new file mode 100644 index 00000000..f80f74f8 --- /dev/null +++ b/test/cypress/support/e2e.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/e2e.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') \ No newline at end of file