From b9aea6a64cb46a0f3239587659239d5ec4222b09 Mon Sep 17 00:00:00 2001 From: Fuhu Xia Date: Mon, 27 Jan 2025 10:31:51 -0500 Subject: [PATCH 1/5] upgrade cypress --- e2e/cypress.config.js | 18 ++++++++++++++++++ e2e/cypress.json | 8 -------- ...xtensions.spec.js => ckan_extensions.cy.js} | 0 .../{dataset.spec.js => dataset.cy.js} | 0 .../{datastore.spec.js => datastore.cy.js} | 0 ..._us_export.spec.js => dcat_us_export.cy.js} | 0 .../integration/{login.spec.js => login.cy.js} | 0 .../{main_page.spec.js => main_page.cy.js} | 0 ...ganizations.spec.js => organizations.cy.js} | 0 ...blic_access.spec.js => public_access.cy.js} | 0 e2e/cypress/support/{index.js => e2e.js} | 0 e2e/package.json | 6 ++++-- 12 files changed, 22 insertions(+), 10 deletions(-) create mode 100644 e2e/cypress.config.js delete mode 100644 e2e/cypress.json rename e2e/cypress/integration/{ckan_extensions.spec.js => ckan_extensions.cy.js} (100%) rename e2e/cypress/integration/{dataset.spec.js => dataset.cy.js} (100%) rename e2e/cypress/integration/{datastore.spec.js => datastore.cy.js} (100%) rename e2e/cypress/integration/{dcat_us_export.spec.js => dcat_us_export.cy.js} (100%) rename e2e/cypress/integration/{login.spec.js => login.cy.js} (100%) rename e2e/cypress/integration/{main_page.spec.js => main_page.cy.js} (100%) rename e2e/cypress/integration/{organizations.spec.js => organizations.cy.js} (100%) rename e2e/cypress/integration/{public_access.spec.js => public_access.cy.js} (100%) rename e2e/cypress/support/{index.js => e2e.js} (100%) diff --git a/e2e/cypress.config.js b/e2e/cypress.config.js new file mode 100644 index 00000000..b65232f3 --- /dev/null +++ b/e2e/cypress.config.js @@ -0,0 +1,18 @@ +const { defineConfig } = require('cypress') + +module.exports = defineConfig({ + reporter: 'junit', + reporterOptions: { + mochaFile: 'cypress/results/output.xml', + }, + videoCompression: false, + e2e: { + // We've imported your old cypress plugins here. + // You may want to clean this up later by importing these. + setupNodeEvents(on, config) { + return require('./cypress/plugins/index.js')(on, config) + }, + specPattern: 'cypress/integration/*.cy.js', + baseUrl: 'http://ckan:5000', + }, +}) diff --git a/e2e/cypress.json b/e2e/cypress.json deleted file mode 100644 index 137dc834..00000000 --- a/e2e/cypress.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "baseUrl": "http://ckan:5000", - "reporter": "junit", - "reporterOptions": { - "mochaFile": "cypress/results/output.xml" - }, - "videoCompression": false -} diff --git a/e2e/cypress/integration/ckan_extensions.spec.js b/e2e/cypress/integration/ckan_extensions.cy.js similarity index 100% rename from e2e/cypress/integration/ckan_extensions.spec.js rename to e2e/cypress/integration/ckan_extensions.cy.js diff --git a/e2e/cypress/integration/dataset.spec.js b/e2e/cypress/integration/dataset.cy.js similarity index 100% rename from e2e/cypress/integration/dataset.spec.js rename to e2e/cypress/integration/dataset.cy.js diff --git a/e2e/cypress/integration/datastore.spec.js b/e2e/cypress/integration/datastore.cy.js similarity index 100% rename from e2e/cypress/integration/datastore.spec.js rename to e2e/cypress/integration/datastore.cy.js diff --git a/e2e/cypress/integration/dcat_us_export.spec.js b/e2e/cypress/integration/dcat_us_export.cy.js similarity index 100% rename from e2e/cypress/integration/dcat_us_export.spec.js rename to e2e/cypress/integration/dcat_us_export.cy.js diff --git a/e2e/cypress/integration/login.spec.js b/e2e/cypress/integration/login.cy.js similarity index 100% rename from e2e/cypress/integration/login.spec.js rename to e2e/cypress/integration/login.cy.js diff --git a/e2e/cypress/integration/main_page.spec.js b/e2e/cypress/integration/main_page.cy.js similarity index 100% rename from e2e/cypress/integration/main_page.spec.js rename to e2e/cypress/integration/main_page.cy.js diff --git a/e2e/cypress/integration/organizations.spec.js b/e2e/cypress/integration/organizations.cy.js similarity index 100% rename from e2e/cypress/integration/organizations.spec.js rename to e2e/cypress/integration/organizations.cy.js diff --git a/e2e/cypress/integration/public_access.spec.js b/e2e/cypress/integration/public_access.cy.js similarity index 100% rename from e2e/cypress/integration/public_access.spec.js rename to e2e/cypress/integration/public_access.cy.js diff --git a/e2e/cypress/support/index.js b/e2e/cypress/support/e2e.js similarity index 100% rename from e2e/cypress/support/index.js rename to e2e/cypress/support/e2e.js diff --git a/e2e/package.json b/e2e/package.json index a9b61f24..9e29ec45 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -5,7 +5,6 @@ "main": "index.js", "dependencies": { "chance": "^1.1.8", - "cypress": "7.3.0", "cypress-downloadfile": "^1.2.1", "cypress-file-upload": "^5.0.8" }, @@ -24,5 +23,8 @@ "bugs": { "url": "https://github.com/gsa/inventory-app/issues" }, - "homepage": "https://github.com/gsa/inventory-app#readme" + "homepage": "https://github.com/gsa/inventory-app#readme", + "devDependencies": { + "cypress": "^12.9.0" + } } From fb4de349aa28551d54d1cec213bafde1d66d7865 Mon Sep 17 00:00:00 2001 From: Fuhu Xia Date: Tue, 28 Jan 2025 11:37:39 -0500 Subject: [PATCH 2/5] upgrade cypress --- .env | 6 +- config/ckan.ini | 5 +- docker-compose.test.yml | 2 +- e2e/cypress.config.js | 6 +- e2e/cypress/integration/ckan_extensions.cy.js | 1 - e2e/cypress/integration/ckan_token.cy.js | 42 +++++++++ e2e/cypress/integration/dataset.cy.js | 37 ++++---- e2e/cypress/integration/datastore.cy.js | 53 ++++++++--- e2e/cypress/integration/dcat_us_export.cy.js | 15 ++- e2e/cypress/integration/main_page.cy.js | 6 -- e2e/cypress/integration/organizations.cy.js | 12 +-- e2e/cypress/integration/public_access.cy.js | 5 +- e2e/cypress/support/command.js | 93 ++++++++++++++++++- e2e/package.json | 2 +- requirements.in.txt | 1 - requirements.txt | 1 - 16 files changed, 224 insertions(+), 63 deletions(-) create mode 100644 e2e/cypress/integration/ckan_token.cy.js diff --git a/.env b/.env index 4ef8340b..22b13841 100644 --- a/.env +++ b/.env @@ -28,7 +28,7 @@ CKAN___API_TOKEN__JWT__DECODE__SECRET=string:CHANGE_ME # Put envvars last per envvars doc, https://github.com/okfn/ckanext-envvars#requirements # Not including saml2auth -CKAN__PLUGINS=datagov_inventory datastore xloader stats text_view recline_view googleanalyticsbasic s3filestore dcat_usmetadata usmetadata datajson envvars +CKAN__PLUGINS=datagov_inventory datastore xloader stats text_view recline_view s3filestore dcat_usmetadata usmetadata datajson envvars CKAN__SITE_TITLE=Inventory CKAN__SITE_LOGO=/base/images/inventory-logo.png @@ -42,6 +42,7 @@ CKAN_SQLALCHEMY_URL=postgresql://ckan:pass@db/ckan CKAN_HOME=/srv/app CKAN_CONFIG=/app/config PORT=5000 +CKAN_SITE_URL=http://ckan:5000 CKAN_DATASTORE_WRITE_URL=postgresql://datastore:pass@datastore/datastore CKAN_DATASTORE_READ_URL=postgresql://datastore_ro:pass@datastore/datastore @@ -102,9 +103,6 @@ CKANEXT__XLOADER__JOB_TIMEOUT=3600 # not be loaded into the datastore. CKANEXT__XLOADER__MAX_EXCERPT_LINES=100 -## google analytics ids -CKANEXT___GOOGLEANALYTICS__IDS=google-analytics-fake-key-testing-87654321 - ## S3Filestore setttings # The maximum content size, in bytes, for uploads CKAN__STORAGE__MAX_CONTENT_LENGTH=650000000 diff --git a/config/ckan.ini b/config/ckan.ini index e3229f1b..3a65f263 100644 --- a/config/ckan.ini +++ b/config/ckan.ini @@ -147,7 +147,7 @@ ckan.cors.origin_whitelist = https://gsa.gov https://www.gsa.gov # same origin policy # Put envvars last per envvars doc, https://github.com/okfn/ckanext-envvars#requirements -ckan.plugins = datagov_inventory datastore xloader stats text_view recline_view googleanalyticsbasic s3filestore dcat_usmetadata usmetadata datajson saml2auth envvars +ckan.plugins = datagov_inventory datastore xloader stats text_view recline_view s3filestore dcat_usmetadata usmetadata datajson saml2auth envvars ckan.views.default_views = recline_view text_view image_view webpage_view recline_grid_view @@ -251,9 +251,6 @@ smtp.starttls = False #smtp.mail_from = error_message = Server Error - Refresh the Page: An internal server error occurred. Try refreshing the page by pressing F5 or Ctrl+F5. -## googleanalyticsbasic, to be configurable https://github.com/GSA/datagov-deploy/issues/2790 -googleanalytics.ids = UA-42145528-2 UA-17367410-17 - ## Logging configuration [loggers] keys = root, ckan, ckanext, datajson diff --git a/docker-compose.test.yml b/docker-compose.test.yml index 3dd4686f..d64423d0 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -3,7 +3,7 @@ services: environment: - CKAN_SITE_URL=http://ckan:5000 test: - image: cypress/included:7.3.0 + image: cypress/included:12.17.2 entrypoint: [] command: /bin/bash -c "npm install && npx wait-on http://ckan:5000/api/action/status_show && cypress run" # To run specific test, use the following syntax: diff --git a/e2e/cypress.config.js b/e2e/cypress.config.js index b65232f3..cafdf663 100644 --- a/e2e/cypress.config.js +++ b/e2e/cypress.config.js @@ -12,7 +12,11 @@ module.exports = defineConfig({ setupNodeEvents(on, config) { return require('./cypress/plugins/index.js')(on, config) }, - specPattern: 'cypress/integration/*.cy.js', baseUrl: 'http://ckan:5000', + specPattern: 'cypress/integration/*.cy.js', + }, + retries: { + runMode: 2, + openMode: 0, }, }) diff --git a/e2e/cypress/integration/ckan_extensions.cy.js b/e2e/cypress/integration/ckan_extensions.cy.js index 2ff042c5..7d5123c0 100644 --- a/e2e/cypress/integration/ckan_extensions.cy.js +++ b/e2e/cypress/integration/ckan_extensions.cy.js @@ -14,7 +14,6 @@ describe('CKAN Extensions', () => { expect(installed_extensions).to.include('xloader'); expect(installed_extensions).to.include('stats'); expect(installed_extensions).to.include('recline_view'); - expect(installed_extensions).to.include('googleanalyticsbasic'); expect(installed_extensions).to.include('s3filestore'); expect(installed_extensions).to.include('envvars'); expect(installed_extensions).to.include('datastore'); diff --git a/e2e/cypress/integration/ckan_token.cy.js b/e2e/cypress/integration/ckan_token.cy.js new file mode 100644 index 00000000..a5f3e45b --- /dev/null +++ b/e2e/cypress/integration/ckan_token.cy.js @@ -0,0 +1,42 @@ +describe('CKAN Token', () => { + + before(() => { + cy.create_token(); + }); + + after(() => { + cy.revoke_token(); + }); + + it('Can get CKAN token', () => { + const token_data = Cypress.env('token_data'); + expect(token_data.api_token).to.have.length(175); + expect(token_data.jti).to.have.length(43); + }); + + it('Can authorize with token', () => { + const token_data = Cypress.env('token_data'); + cy.logout(); + + // 403 without token + cy.request({ + method: 'GET', + url: '/api/action/package_search', + failOnStatusCode: false, + }).then((response) => { + expect(response.status).to.eq(403); + }); + + // 200 with token + cy.request({ + method: 'GET', + url: '/api/action/package_search', + headers: { + 'Authorization': token_data.api_token + } + }).then((response) => { + expect(response.status).to.eq(200); + }); + }); + +}) diff --git a/e2e/cypress/integration/dataset.cy.js b/e2e/cypress/integration/dataset.cy.js index c80e8474..f614c8d4 100644 --- a/e2e/cypress/integration/dataset.cy.js +++ b/e2e/cypress/integration/dataset.cy.js @@ -1,19 +1,16 @@ describe('Dataset', () => { before(() => { + cy.create_token(); cy.logout(); - cy.login(); cy.delete_organization('test-organization'); cy.create_organization('test-organization', 'Test organization'); }); - - beforeEach(() => { - Cypress.Cookies.preserveOnce('auth_tkt', 'ckan'); - }); after(() => { cy.delete_dataset('test-dataset-1'); cy.delete_organization('test-organization'); + cy.revoke_token(); }); it('Creates dataset via API', () => { @@ -25,32 +22,41 @@ describe('Dataset', () => { }); it('Has a details page with core metadata', () => { + cy.login(); cy.visit('/dataset/test-dataset-1'); cy.contains('Test Dataset 1'); cy.contains('DCAT-US Metadata'); }); it('Add resource to private dataset via API', () => { + const token_data = Cypress.env('token_data'); + cy.logout(); cy.fixture('ckan_resource.csv', 'binary').then((ckan_resource) => { // File in binary format gets converted to blob so it can be sent as Form data const blob = Cypress.Blob.binaryStringToBlob(ckan_resource) const formData = new FormData(); - formData.set('upload', blob, 'ckan_resource.csv'); //adding a file to the form - formData.set('package_id', "test-dataset-1"); - formData.set('name', "test-resource-1"); - formData.set('resource_type', "CSV"); - formData.set('format', "CSV"); - cy.form_request('POST', '/api/action/resource_create', formData, function (response) { + formData.append('upload', blob, 'ckan_resource.csv'); //adding a file to the form + formData.append('package_id', "test-dataset-1"); + formData.append('name', "test-resource-1"); + formData.append('resource_type', "CSV"); + formData.append('format', "CSV"); + cy.request({ + method: 'POST', + url: '/api/action/resource_create', + body: formData, + headers: { + 'Content-Type': 'multipart/form-data', + 'Authorization': token_data.api_token + } + }).then((response) => { expect(response.status).to.eq(200); }); }); - cy.visit('/dataset'); }); it('Download resource file', () => { + cy.login(); cy.visit('/dataset/test-dataset-1') - // Hide flask debug toolbar - cy.get('#flDebugHideToolBarButton').click(); // Open resource dropdown cy.get('.dropdown-toggle').click() // Download resource file @@ -62,9 +68,8 @@ describe('Dataset', () => { it('Download resource file', () => { // Test download as anonymous user + cy.login(); cy.visit('/dataset/test-dataset-1') - // Hide flask debug toolbar - cy.get('#flDebugHideToolBarButton').click(); // Open resource dropdown cy.get('.dropdown-toggle').click(); // Download resource file diff --git a/e2e/cypress/integration/datastore.cy.js b/e2e/cypress/integration/datastore.cy.js index 4bc73fdc..b82dd967 100644 --- a/e2e/cypress/integration/datastore.cy.js +++ b/e2e/cypress/integration/datastore.cy.js @@ -1,31 +1,36 @@ describe('Datastore', () => { before(() => { - cy.login(); + cy.create_token(); + cy.logout(); cy.delete_organization('test-organization'); cy.create_organization('test-organization', 'Test organization'); }) - beforeEach(() => { - Cypress.Cookies.preserveOnce('auth_tkt', 'ckan') - }) - after(() => { cy.delete_dataset('test-dataset-1') cy.delete_organization('test-organization') + cy.revoke_token(); }) it('Is installed and available via CKAN API', () => { - cy.request('/api/3/action/datastore_search?resource_id=_table_metadata') - .should((response) => { + const token_data = Cypress.env('token_data'); + cy.request({ + method: 'GET', + url: '/api/3/action/datastore_search?resource_id=_table_metadata', + headers: { + 'Authorization': token_data.api_token + } + }).should((response) => { expect(response.body).to.have.property('success', true) }); }); it('Can create datastore resource via API', () => { + const token_data = Cypress.env('token_data'); // First create dataset cy.fixture('ckan_dataset.json').then((ckan_dataset) => { - cy.create_dataset(ckan_dataset).should((response) => { + cy.create_dataset(ckan_dataset).then((response) => { expect(response.body).to.have.property('success', true) // Create resource with datastore_create api @@ -34,7 +39,8 @@ describe('Datastore', () => { 'url': '/api/3/action/datastore_create', 'headers': { 'cache-control': 'no-cache', - 'content-type': 'application/json' + 'content-type': 'application/json', + 'Authorization': token_data.api_token }, body: JSON.stringify({ "resource": {"package_id": response.body.result.id}, @@ -50,10 +56,23 @@ describe('Datastore', () => { }) it('Can access datastore API', () => { - cy.request('/api/action/package_show?id=test-dataset-1').then((response) => { + const token_data = Cypress.env('token_data'); + cy.request({ + method: 'GET', + url: '/api/action/package_show?id=test-dataset-1', + headers: { + 'Authorization': token_data.api_token + } + }).then((response) => { expect(response.body).to.have.property('success', true); const resource_id = response.body.result.resources[0].id; - cy.request(`/api/action/datastore_search?resource_id=${resource_id}`).should((response) => { + cy.request({ + method: 'GET', + url: `/api/action/datastore_search?resource_id=${resource_id}`, + headers: { + 'Authorization': token_data.api_token + } + }).should((response) => { expect(response.body).to.have.property('success', true); expect(response.body.result).to.have.property('total', 2); }); @@ -61,7 +80,14 @@ describe('Datastore', () => { }) it('Can delete datastore resource via API', () => { - cy.request('/api/action/package_show?id=test-dataset-1').then((response) => { + const token_data = Cypress.env('token_data'); + cy.request({ + method: 'GET', + url: '/api/action/package_show?id=test-dataset-1', + headers: { + 'Authorization': token_data.api_token + } + }).then((response) => { expect(response.body).to.have.property('success', true); const resource_id = response.body.result.resources[0].id; // delete resource with datastore_delete api @@ -70,7 +96,8 @@ describe('Datastore', () => { 'url': '/api/3/action/datastore_delete', 'headers': { 'cache-control': 'no-cache', - 'content-type': 'application/json' + 'content-type': 'application/json', + 'Authorization': token_data.api_token }, body: JSON.stringify({ "resource_id": resource_id, diff --git a/e2e/cypress/integration/dcat_us_export.cy.js b/e2e/cypress/integration/dcat_us_export.cy.js index cdf836da..a7bce885 100644 --- a/e2e/cypress/integration/dcat_us_export.cy.js +++ b/e2e/cypress/integration/dcat_us_export.cy.js @@ -3,9 +3,12 @@ import 'cypress-file-upload'; describe('DCAT-US Export', () => { const dataset_title = 'test-dataset-2'; + before(() => { + cy.create_token(); + }); + beforeEach(() => { cy.logout(); - cy.login(); cy.delete_dataset('test-dataset-1'); cy.delete_dataset('test-dataset-2'); cy.delete_dataset('test-sub-dataset-1'); @@ -44,9 +47,14 @@ describe('DCAT-US Export', () => { }); }); cy.exec('rm cypress/downloads/draft*', { failOnNonZeroExit: false }); + cy.exec('rm cypress/downloads/redacted.zip', { failOnNonZeroExit: false }); + cy.exec('rm cypress/downloads/data.json', { failOnNonZeroExit: false }); + + cy.login(); }); - afterEach(() => { + after(() => { + cy.logout(); cy.delete_dataset('test-dataset-1'); cy.delete_dataset('test-dataset-2'); cy.delete_dataset('test-sub-dataset-1'); @@ -55,6 +63,9 @@ describe('DCAT-US Export', () => { cy.delete_organization('test-organization'); cy.delete_organization('test-sub-organization'); cy.exec('rm cypress/downloads/draft*', { failOnNonZeroExit: false }); + cy.exec('rm cypress/downloads/redacted.zip', { failOnNonZeroExit: false }); + cy.exec('rm cypress/downloads/data.json', { failOnNonZeroExit: false }); + cy.revoke_token(); }); it('Can create a zip export of the organization drafts', () => { diff --git a/e2e/cypress/integration/main_page.cy.js b/e2e/cypress/integration/main_page.cy.js index 22db0e4e..2c1fd27a 100644 --- a/e2e/cypress/integration/main_page.cy.js +++ b/e2e/cypress/integration/main_page.cy.js @@ -1,7 +1,6 @@ describe('Main Page', () => { beforeEach(() => { - cy.logout(); cy.login(); }); @@ -10,9 +9,4 @@ describe('Main Page', () => { cy.contains('Inventory'); }); - it('google tracker injected', () => { - cy.request('/dataset').then((response) => { - expect(response.body).to.have.string('google-analytics-fake-key-testing-87654321'); - }); - }); }) diff --git a/e2e/cypress/integration/organizations.cy.js b/e2e/cypress/integration/organizations.cy.js index 5db6734c..4c467656 100644 --- a/e2e/cypress/integration/organizations.cy.js +++ b/e2e/cypress/integration/organizations.cy.js @@ -1,22 +1,25 @@ describe('Organization', () => { before(() => { - cy.login() + cy.create_token(); }) + beforeEach(() => { - Cypress.Cookies.preserveOnce('auth_tkt', 'ckan') + cy.login() }) + after(() => { cy.delete_organization('cypress-test-org') + cy.revoke_token() }) it('Create Organization', () => { cy.visit('/organization') cy.get('a[class="btn btn-primary"]').click() cy.create_organization_ui('cypress-test-org', 'cypress test description') - cy.visit('/organization/cypress-test-org') }) it('Contains Organization Information', () => { + cy.visit('/organization/cypress-test-org') cy.contains('No datasets found') cy.contains('cypress test description') cy.contains('0') @@ -26,9 +29,6 @@ describe('Organization', () => { it('Edit Organization Description', () => { cy.visit('/organization/edit/cypress-test-org') - // Hide flask debug toolbar - cy.get('#flDebugHideToolBarButton').click(); - cy.get('#field-description').clear() cy.get('#field-description').type('the new description') cy.get('button[name=save]').click() diff --git a/e2e/cypress/integration/public_access.cy.js b/e2e/cypress/integration/public_access.cy.js index fe19433e..ea685356 100644 --- a/e2e/cypress/integration/public_access.cy.js +++ b/e2e/cypress/integration/public_access.cy.js @@ -1,7 +1,7 @@ describe('Public Access', () => { before(() => { + cy.create_token(); cy.logout(); - cy.login(); cy.delete_organization('test-organization'); cy.create_organization('test-organization', 'Test organization'); cy.fixture('ckan_dataset.json').then((ckan_dataset) => { @@ -13,10 +13,9 @@ describe('Public Access', () => { }); after(() => { - cy.login(); - cy.wait(2000); cy.delete_dataset('test-dataset-1'); cy.delete_organization('test-organization'); + cy.revoke_token(); }); it('Cannot access the standard public pages', () => { diff --git a/e2e/cypress/support/command.js b/e2e/cypress/support/command.js index 6a54339b..6f158eeb 100644 --- a/e2e/cypress/support/command.js +++ b/e2e/cypress/support/command.js @@ -16,13 +16,14 @@ function verify_element_exists() { }); } -Cypress.Commands.add('login', (userName, password, loginTest) => { +Cypress.Commands.add('login', (userName, password) => { /** * Method to fill and submit the CKAN Login form * :PARAM userName String: user name of that will be attempting to login * :PARAM password String: password for the user logging in * :RETURN null: */ + cy.logout(); cy.visit('/user/login'); if (!userName) { @@ -39,12 +40,73 @@ Cypress.Commands.add('login', (userName, password, loginTest) => { cy.get('#field-login').type(userName); cy.get('#field-password').type(password); cy.get('.btn-primary').click(); + }); Cypress.Commands.add('logout', () => { cy.clearCookies(); }); + +Cypress.Commands.add('create_token', (tokenName) => { + // return if token already exists + const token_data = Cypress.env('token_data'); + + if (token_data) { + cy.log('Token already exists. skipping token creation.'); + return; + } + + cy.login(); + + if (!tokenName) { + tokenName = 'cypress token'; + } + + const userName = Cypress.env('USER'); + // create an API token named 'cypress token' + cy.visit('/user/' + userName + '/api-tokens'); + + cy.get('body').then($body => { + cy.get('#name').type('cypress token'); + cy.get('button[value="create"]').click(); + // find the token in tag and save it for later use + // find the token id (jti) somewhere in the form + cy.get('div.alert-success code').invoke('text').then((text1) => { + cy.get('form[action^="/user/' + userName +'/api-tokens/"]').invoke('attr', 'action').then((text2) => { + const jti = text2.split('/')[4] + Cypress.env('token_data', { api_token: text1, jti: jti }); + }) + }); + cy.log('cypress token created.'); + }); + +}); + +Cypress.Commands.add('revoke_token', (tokenName) => { + + const token_data = Cypress.env('token_data'); + + if (!token_data) { + return; + } + + if (!tokenName) { + tokenName = 'cypress token'; + } + cy.log('Revoking cypress token.......'); + cy.request({ + url: '/api/3/action/api_token_revoke', + method: 'POST', + headers: { + 'Authorization': token_data.api_token, + 'Content-Type': 'application/json' + }, + body: '{"jti": "' + token_data.jti + '"}' + }); +}); + + Cypress.Commands.add('create_organization_ui', (orgName, orgDesc) => { /** * Method to fill out the form to create a CKAN organization @@ -73,10 +135,15 @@ Cypress.Commands.add('create_organization', (orgName, orgDesc, extras = null) => * for testing or to visit the organization creation page * :RETURN null: */ + const token_data = Cypress.env('token_data'); let request_obj = { url: '/api/action/organization_create', method: 'POST', + headers: { + 'Authorization': token_data.api_token, + 'Content-Type': 'application/json' + }, body: { description: orgDesc, title: orgName, @@ -99,40 +166,58 @@ Cypress.Commands.add('create_organization', (orgName, orgDesc, extras = null) => cy.request(request_obj); }); + Cypress.Commands.add('delete_organization', (orgName) => { /** * Method to purge an organization from the current state * :PARAM orgName String: Name of the organization to purge from the current state * :RETURN null: */ + const token_data = Cypress.env('token_data'); + cy.request({ url: '/api/action/organization_delete', method: 'POST', failOnStatusCode: false, + headers: { + 'Authorization': token_data.api_token, + 'Content-Type': 'application/json' + }, body: { - id: orgName, + id: orgName? orgName: 'test-organization' }, }); + cy.request({ url: '/api/action/organization_purge', method: 'POST', failOnStatusCode: false, + headers: { + 'Authorization': token_data.api_token, + 'Content-Type': 'application/json' + }, body: { - id: orgName, + id: orgName? orgName: 'test-organization' }, }); }); + Cypress.Commands.add('delete_dataset', (datasetName) => { /** * Method to purge a dataset from the current state * :PARAM datasetName String: Name of the dataset to purge from the current state * :RETURN null: */ + const token_data = Cypress.env('token_data'); cy.request({ url: '/api/action/dataset_purge', method: 'POST', failOnStatusCode: false, + headers: { + 'Authorization': token_data.api_token, + 'Content-Type': 'application/json' + }, body: { id: datasetName, }, @@ -197,12 +282,14 @@ Cypress.Commands.add('start_harvest_job', (harvestName) => { }); Cypress.Commands.add('create_dataset', (ckan_dataset) => { + const token_data = Cypress.env('token_data'); var options = { method: 'POST', url: '/api/3/action/package_create', headers: { 'cache-control': 'no-cache', 'content-type': 'application/json', + 'Authorization': token_data.api_token, }, body: JSON.stringify(ckan_dataset), }; diff --git a/e2e/package.json b/e2e/package.json index 9e29ec45..c90ca010 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -25,6 +25,6 @@ }, "homepage": "https://github.com/gsa/inventory-app#readme", "devDependencies": { - "cypress": "^12.9.0" + "cypress": "^12.17.2" } } diff --git a/requirements.in.txt b/requirements.in.txt index a0d714b0..dce64e74 100644 --- a/requirements.in.txt +++ b/requirements.in.txt @@ -4,7 +4,6 @@ git+https://github.com/GSA/ckanext-saml2auth.git@datagov#egg=ckanext-saml2auth git+https://github.com/keitaroinc/ckanext-s3filestore.git#egg=ckanext-s3filestore -e git+https://github.com/ckan/ckanext-xloader.git@master#egg=ckanext-xloader -ckanext-googleanalyticsbasic ckanext-usmetadata>=0.3.2 ckanext-datajson>=0.1.19 ckanext-dcat-usmetadata~=0.6.0 diff --git a/requirements.txt b/requirements.txt index 2fcbe4d0..a40073da 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,7 +15,6 @@ ckan @ git+https://github.com/GSA/ckan.git@8c4a517efeac80db098cc6ba144cb742bbeca ckanext-datajson==0.1.27 ckanext-dcat-usmetadata==0.6.0 ckanext-envvars==0.0.6 -ckanext-googleanalyticsbasic==0.2.1 ckanext-s3filestore @ git+https://github.com/keitaroinc/ckanext-s3filestore.git@caf88c0352ffe7b4432d3d55ddfb0a71249ceddd ckanext-saml2auth @ git+https://github.com/GSA/ckanext-saml2auth.git@387cfc1c6a7619f670bf387384f2634516de5844 ckanext-usmetadata==0.3.2 From 0c7a9bb23e78ae24fd208b72d68cbc48d95527ad Mon Sep 17 00:00:00 2001 From: Fuhu Xia Date: Tue, 28 Jan 2025 12:40:17 -0500 Subject: [PATCH 3/5] add unzip --- docker-compose.test.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docker-compose.test.yml b/docker-compose.test.yml index d64423d0..90d91081 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -5,7 +5,12 @@ services: test: image: cypress/included:12.17.2 entrypoint: [] - command: /bin/bash -c "npm install && npx wait-on http://ckan:5000/api/action/status_show && cypress run" + command: /bin/bash -c " + apt-get update && \ + apt-get install -y unzip && \ + npm install && \ + npx wait-on http://ckan:5000/api/action/status_show && \ + cypress run " # To run specific test, use the following syntax: # command: /bin/bash -c "npm install && npx wait-on http://ckan:5000/api/action/status_show && cypress run --spec cypress/integration/dcat_us_export.spec.js" # command: /bin/bash -c "npm install && npx wait-on http://ckan:5000/api/action/status_show && cypress run --spec cypress/integration/login.spec.js" From ed133a5e2eafd2d950d01c86e84b9292636611c6 Mon Sep 17 00:00:00 2001 From: Fuhu Xia Date: Wed, 29 Jan 2025 10:05:56 -0500 Subject: [PATCH 4/5] minor change --- e2e/cypress/support/command.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/cypress/support/command.js b/e2e/cypress/support/command.js index 6f158eeb..bf98ad53 100644 --- a/e2e/cypress/support/command.js +++ b/e2e/cypress/support/command.js @@ -102,7 +102,7 @@ Cypress.Commands.add('revoke_token', (tokenName) => { 'Authorization': token_data.api_token, 'Content-Type': 'application/json' }, - body: '{"jti": "' + token_data.jti + '"}' + body: {jti: token_data.jti} }); }); From 421e04bb978ef11290c4627afa4f087f8838c48e Mon Sep 17 00:00:00 2001 From: Fuhu Xia Date: Wed, 29 Jan 2025 19:01:15 -0500 Subject: [PATCH 5/5] fix chrome/deb NO_PUBKEY --- docker-compose.test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.test.yml b/docker-compose.test.yml index 90d91081..282a14e7 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -6,6 +6,7 @@ services: image: cypress/included:12.17.2 entrypoint: [] command: /bin/bash -c " + rm -rf /etc/apt/sources.list.d/google-chrome.list && \ apt-get update && \ apt-get install -y unzip && \ npm install && \