diff --git a/.github/workflows/ui-smoketest.yml b/.github/workflows/ui-smoketest.yml index 4fd43f546..34af264f6 100644 --- a/.github/workflows/ui-smoketest.yml +++ b/.github/workflows/ui-smoketest.yml @@ -26,7 +26,6 @@ permissions: contents: read # This is required for actions/checkout jobs: - cypress-run-chrome: runs-on: ubuntu-22.04 environment: ${{ github.event.inputs.environment }} @@ -51,8 +50,23 @@ jobs: env: CYPRESS_BASE_URL: 'https://${{ github.event.inputs.sandbox }}.access-request-fulfilment.patient-deductions.nhs.uk' CYPRESS_grepTags: 'smoke' + CYPRESS_WORKSPACE: ${{ github.event.inputs.sandbox }} CYPRESS_USERNAME: ${{ secrets.CYPRESS_USERNAME }} CYPRESS_PASSWORD: ${{ secrets.CYPRESS_PASSWORD }} + CYPRESS_OUTPUT_VIDEO: true + + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: cypress-screenshots + path: /home/runner/work/national-document-repository/national-document-repository/app/cypress/screenshots + if-no-files-found: ignore + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: cypress-videos + path: /home/runner/work/national-document-repository/national-document-repository/app/cypress/videos + if-no-files-found: ignore cypress-run-firefox: runs-on: ubuntu-22.04 @@ -64,6 +78,13 @@ jobs: repository: 'nhsconnect/national-document-repository' ref: ${{ github.event.inputs.build_branch}} + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v2 + with: + role-to-assume: ${{ secrets.AWS_ASSUME_ROLE }} + role-skip-session-tagging: true + aws-region: ${{ vars.AWS_REGION }} + - name: Cypress install run: | npm install --legacy-peer-deps @@ -78,8 +99,10 @@ jobs: env: CYPRESS_BASE_URL: 'https://${{ github.event.inputs.sandbox }}.access-request-fulfilment.patient-deductions.nhs.uk' CYPRESS_grepTags: 'smoke' + CYPRESS_WORKSPACE: ${{ github.event.inputs.sandbox }} CYPRESS_USERNAME: ${{ secrets.CYPRESS_USERNAME }} CYPRESS_PASSWORD: ${{ secrets.CYPRESS_PASSWORD }} + CYPRESS_OUTPUT_VIDEO: false cypress-run-edge: runs-on: ubuntu-22.04 @@ -105,5 +128,7 @@ jobs: env: CYPRESS_BASE_URL: 'https://${{ github.event.inputs.sandbox }}.access-request-fulfilment.patient-deductions.nhs.uk' CYPRESS_grepTags: 'smoke' + CYPRESS_WORKSPACE: ${{ github.event.inputs.sandbox }} CYPRESS_USERNAME: ${{ secrets.CYPRESS_USERNAME }} CYPRESS_PASSWORD: ${{ secrets.CYPRESS_PASSWORD }} + CYPRESS_OUTPUT_VIDEO: false diff --git a/app/.env.template b/app/.env.template index 40d33ddb0..d44b03365 100644 --- a/app/.env.template +++ b/app/.env.template @@ -7,6 +7,12 @@ REACT_APP_IMAGE_VERSION="%IMAGE_VERSION%" CONTAINER_PORT=xx # Port number within the container. Needed for building the docker image HOST_PORT=xxxx # Port number that the docker-compose localhost exposes. Only need this if we run docker-compose PORT=xxxx # Port number of the localhost dev server when we run `make start` + +# Cypress Smoke Testing CYPRESS_BASE_URL=http://localhost:xxxx # Use the port number same as above PORT CYPRESS_USERNAME=xxxx # For Cypress CIS2 Login during smoke tests CYPRESS_PASSWORD=xxxx # For Cypress CIS2 Login during smoke tests +CYPRESS_WORKSPACE=local # Helps find the correct patient data relative to the workspace +AWS_ACCESS_KEY_ID=xxxx # If workspace is a sandbox, data is seeded with these credentials +AWS_SECRET_ACCESS_KEY=xxxx # If workspace is a sandbox, data is seeded with these credentials +AWS_SESSION_TOKEN=xxxx # If workspace is a sandbox, data is seeded with these credentials diff --git a/app/cypress.config.ts b/app/cypress.config.ts index 6d8c37e00..c6ac7b536 100644 --- a/app/cypress.config.ts +++ b/app/cypress.config.ts @@ -14,6 +14,11 @@ export default defineConfig({ env: { USERNAME: process.env.CYPRESS_USERNAME, PASSWORD: process.env.CYPRESS_PASSWORD, + WORKSPACE: process.env.CYPRESS_WORKSPACE ?? 'local', + AWS_ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID, + AWS_SECRET_ACCESS_KEY: process.env.AWS_SECRET_ACCESS_KEY, + AWS_REGION: process.env.AWS_REGION, + AWS_SESSION_TOKEN: process.env.AWS_SESSION_TOKEN, }, component: { devServer: { @@ -28,4 +33,6 @@ export default defineConfig({ html: false, json: true, }, + video: process.env.CYPRESS_OUTPUT_VIDEO ? true : false, + videoCompression: 15, }); diff --git a/app/cypress/e2e/0-ndr-core-tests/homepage.cy.js b/app/cypress/e2e/0-ndr-core-tests/homepage.cy.js index 5f5bac141..88803fecd 100644 --- a/app/cypress/e2e/0-ndr-core-tests/homepage.cy.js +++ b/app/cypress/e2e/0-ndr-core-tests/homepage.cy.js @@ -12,6 +12,25 @@ describe('Home Page', () => { cy.url().should('eq', baseUrl + homeUrl); }); + it('displays correct page title on home page', { tags: 'regression' }, () => { + cy.get('.app-homepage-content h1').should( + 'have.text', + 'Access and store digital GP records', + ); + }); + + it('displays start now button on home page', { tags: 'regression' }, () => { + cy.get('.nhsuk-button').should('have.text', 'Start now'); + }); + + it('displays service banner', { tags: 'regression' }, () => { + cy.get('.govuk-phase-banner__content__tag').should('have.text', 'New Service'); + cy.get('.govuk-phase-banner__text').should( + 'have.text', + 'Your feedback will help us to improve this service.', + ); + }); + context('Login tests', () => { it( 'should display patient search page with navigation after user log in from homepage', @@ -42,37 +61,44 @@ describe('Home Page', () => { }); context('Logout tests', () => { - // TODO: Align with smoke logout test it( 'should display home page with no navigation after user log out', { tags: 'regression' }, () => { - cy.get('header').should('have.length', 1); + cy.get('header').should('exist'); - cy.get('.nhsuk-logo__background').should('have.length', 1); - cy.get('.nhsuk-header__transactional-service-name').should('have.length', 1); + cy.get('.nhsuk-logo__background').should('exist'); + cy.get('.nhsuk-header__transactional-service-name').should('exist'); cy.get('.nhsuk-header__transactional-service-name') .children() .should('have.length', 1); + cy.get('.nhsuk-header__transactional-service-name--link').should('exist'); cy.get('.nhsuk-header__transactional-service-name--link').should( 'have.text', 'Access and store digital GP records', ); + cy.get('.nhsuk-header__navigation').should('not.exist'); + cy.get('.nhsuk-header__navigation-list').should('not.exist'); - cy.get('.nhsuk-header__navigation').should('have.length', 0); - cy.get('.nhsuk-header__navigation-list').should('have.length', 0); - }, - ); + cy.login(Roles.GP_CLINICAL); + + cy.url().should('eq', baseUrl + searchUrl); + cy.get('.nhsuk-header__navigation').should('exist'); + cy.get('.nhsuk-header__navigation-list').should('exist'); - it('displays correct page title on home page', { tags: 'regression' }, () => { - cy.get('.app-homepage-content h1').should( - 'have.text', - 'Access and store digital GP records', - ); - }); + cy.intercept('GET', '/Auth/Logout', { + statusCode: 200, + }).as('logout'); - it('displays start now button on home page', { tags: 'regression' }, () => { - cy.get('.nhsuk-button').should('have.text', 'Start now'); - }); + cy.getByTestId('logout-btn').should('exist'); + cy.getByTestId('logout-btn').click(); + + cy.wait('@logout'); + cy.url({ timeout: 10000 }).should('contain', baseUrl + homeUrl); + + cy.get('.nhsuk-header__navigation').should('not.exist'); + cy.get('.nhsuk-header__navigation-list').should('not.exist'); + }, + ); }); }); diff --git a/app/cypress/e2e/0-ndr-core-tests/pcse_user_workflows/patient_search_and_verify_workflow.cy.js b/app/cypress/e2e/0-ndr-core-tests/pcse_user_workflows/patient_search_and_verify_workflow.cy.js index 6f1f1c790..6fd10fdc5 100644 --- a/app/cypress/e2e/0-ndr-core-tests/pcse_user_workflows/patient_search_and_verify_workflow.cy.js +++ b/app/cypress/e2e/0-ndr-core-tests/pcse_user_workflows/patient_search_and_verify_workflow.cy.js @@ -4,12 +4,11 @@ describe('PCSE Workflow: patient search and verify', () => { // env vars const baseUrl = Cypress.config('baseUrl'); const homeUrl = '/'; - const testPatient = '9000000009'; const patient = { birthDate: '1970-01-01', familyName: 'Default Surname', givenName: ['Default Given Name'], - nhsNumber: testPatient, + nhsNumber: '9000000009', postalCode: 'AA1 1AA', superseded: false, restricted: false, @@ -19,37 +18,11 @@ describe('PCSE Workflow: patient search and verify', () => { cy.visit(homeUrl); }); - it( - 'It redirects to the patient download screen when patient search successfully by a PCSE user', - { tags: 'regression' }, - () => { - cy.intercept('GET', '/SearchPatient*', { - statusCode: 200, - body: patient, - }).as('search'); - - cy.login(Roles.PCSE); - cy.get('#nhs-number-input').click(); - cy.get('#nhs-number-input').type(testPatient); - - cy.get('#search-submit').click(); - cy.wait('@search'); - - cy.url().should('include', 'result'); - cy.url().should('eq', baseUrl + '/search/patient/result'); - cy.get('#gp-message').should('not.exist'); - - cy.get('#verify-submit').click(); - - cy.url().should('include', 'results'); - cy.url().should('eq', baseUrl + '/search/results'); - }, - ); - it( 'It shows the download documents page when download patient is verified by a PCSE user', { tags: 'regression' }, () => { + const testPatient = '9000000009'; cy.login(Roles.PCSE); cy.intercept('GET', '/SearchPatient*', { statusCode: 200, @@ -66,31 +39,11 @@ describe('PCSE Workflow: patient search and verify', () => { }, ); - it( - 'It searches for a valid patient successfully when the user enters a known nhs number by a PCSE user', - { tags: 'regression' }, - () => { - cy.intercept('GET', '/SearchPatient*', { - statusCode: 200, - body: patient, - }).as('search'); - - cy.login(Roles.PCSE); - cy.get('#nhs-number-input').click(); - cy.get('#nhs-number-input').type(testPatient); - - cy.get('#search-submit').click(); - cy.wait('@search'); - - cy.url().should('include', 'result'); - cy.url().should('eq', baseUrl + '/search/patient/result'); - }, - ); - it( 'It searches for a valid patient successfully when the user enters a known nhs number with spaces by a PCSE user', { tags: 'regression' }, () => { + const testPatient = '900 000 0009'; cy.intercept('GET', '/SearchPatient*', { statusCode: 200, body: { @@ -114,6 +67,7 @@ describe('PCSE Workflow: patient search and verify', () => { 'It searches for a valid patient successfully when the user enters a known nhs number with dashes by a PCSE user', { tags: 'regression' }, () => { + const testPatient = '900-000-0009'; cy.intercept('GET', '/SearchPatient*', { statusCode: 200, body: { diff --git a/app/cypress/e2e/1-ndr-smoke-tests/gp_user_workflows/patient_search_and_verify_workflow.cy.js b/app/cypress/e2e/1-ndr-smoke-tests/gp_user_workflows/patient_search_and_verify_workflow.cy.js new file mode 100644 index 000000000..ef982f42c --- /dev/null +++ b/app/cypress/e2e/1-ndr-smoke-tests/gp_user_workflows/patient_search_and_verify_workflow.cy.js @@ -0,0 +1,33 @@ +import { Roles, roleName } from '../../../support/roles'; + +describe('GP Workflow: Patient search and verify', () => { + // env vars + const baseUrl = Cypress.config('baseUrl'); + const gpRoles = [Roles.GP_ADMIN, Roles.GP_CLINICAL]; + + const workspace = Cypress.env('WORKSPACE'); + const activePatient = workspace === 'ndr-dev' ? '9730153817' : '9000000002'; + + gpRoles.forEach((role) => { + it( + `[Smoke] Shows the Lloyd george view page when upload patient is verified and active as a ${roleName( + role, + )} `, + { tags: 'smoke' }, + () => { + cy.smokeLogin(role); + cy.get('#nhs-number-input').click(); + cy.get('#nhs-number-input').type(activePatient); + cy.get('#search-submit').click(); + + cy.url({ timeout: 10000 }).should('eq', baseUrl + '/search/upload/result'); + cy.get('#verify-submit').click(); + + cy.url({ timeout: 10000 }).should( + 'eq', + baseUrl + '/search/patient/lloyd-george-record', + ); + }, + ); + }); +}); diff --git a/app/cypress/e2e/1-ndr-smoke-tests/homepage.cy.js b/app/cypress/e2e/1-ndr-smoke-tests/homepage.cy.js index 96691d02b..207198e86 100644 --- a/app/cypress/e2e/1-ndr-smoke-tests/homepage.cy.js +++ b/app/cypress/e2e/1-ndr-smoke-tests/homepage.cy.js @@ -13,30 +13,68 @@ describe('Home Page', () => { cy.url().should('eq', baseUrl + homeUrl); }); - it( - '[Smoke] should display patient search page with navigation after user log in from homepage', - { tags: 'smoke' }, - () => { - cy.get('header').should('exist'); - - cy.get('.nhsuk-logo__background').should('exist'); - cy.get('.nhsuk-header__transactional-service-name').should('exist'); - cy.get('.nhsuk-header__transactional-service-name').children().should('have.length', 1); - cy.get('.nhsuk-header__transactional-service-name--link').should('exist'); - cy.get('.nhsuk-header__transactional-service-name--link').should( - 'have.text', - 'Access and store digital GP records', - ); - cy.get('.nhsuk-header__navigation').should('not.exist'); - cy.get('.nhsuk-header__navigation-list').should('not.exist'); - - cy.smokeLogin(Roles.GP_CLINICAL); - - cy.url().should('eq', baseUrl + searchUrl); - cy.get('.nhsuk-header__navigation').should('exist'); - cy.get('.nhsuk-header__navigation-list').should('exist'); - }, - - //TODO: Add logout test - ); + context('Login tests', () => { + it( + '[Smoke] should display patient search page with navigation after user log in from homepage', + { tags: 'smoke' }, + () => { + cy.get('header').should('exist'); + + cy.get('.nhsuk-logo__background').should('exist'); + cy.get('.nhsuk-header__transactional-service-name').should('exist'); + cy.get('.nhsuk-header__transactional-service-name') + .children() + .should('have.length', 1); + cy.get('.nhsuk-header__transactional-service-name--link').should('exist'); + cy.get('.nhsuk-header__transactional-service-name--link').should( + 'have.text', + 'Access and store digital GP records', + ); + cy.get('.nhsuk-header__navigation').should('not.exist'); + cy.get('.nhsuk-header__navigation-list').should('not.exist'); + + cy.smokeLogin(Roles.GP_CLINICAL); + + cy.url().should('eq', baseUrl + searchUrl); + cy.get('.nhsuk-header__navigation').should('exist'); + cy.get('.nhsuk-header__navigation-list').should('exist'); + }, + ); + }); + + context('Logout tests', () => { + it( + '[Smoke] should display home page with no navigation after user log out', + { tags: 'smoke' }, + () => { + cy.get('header').should('exist'); + + cy.get('.nhsuk-logo__background').should('exist'); + cy.get('.nhsuk-header__transactional-service-name').should('exist'); + cy.get('.nhsuk-header__transactional-service-name') + .children() + .should('have.length', 1); + cy.get('.nhsuk-header__transactional-service-name--link').should('exist'); + cy.get('.nhsuk-header__transactional-service-name--link').should( + 'have.text', + 'Access and store digital GP records', + ); + cy.get('.nhsuk-header__navigation').should('not.exist'); + cy.get('.nhsuk-header__navigation-list').should('not.exist'); + + cy.smokeLogin(Roles.GP_CLINICAL); + + cy.url().should('eq', baseUrl + searchUrl); + cy.get('.nhsuk-header__navigation').should('exist'); + cy.get('.nhsuk-header__navigation-list').should('exist'); + + cy.getByTestId('logout-btn').should('exist'); + cy.getByTestId('logout-btn').click(); + cy.url({ timeout: 10000 }).should('eq', baseUrl + homeUrl); + + cy.get('.nhsuk-header__navigation').should('not.exist'); + cy.get('.nhsuk-header__navigation-list').should('not.exist'); + }, + ); + }); }); diff --git a/app/cypress/support/aws.commands.ts b/app/cypress/support/aws.commands.ts index 9184316ff..3b80ac47b 100644 --- a/app/cypress/support/aws.commands.ts +++ b/app/cypress/support/aws.commands.ts @@ -2,34 +2,60 @@ import AWS from './aws.config'; -Cypress.Commands.add('addFileToS3', (bucketName, fileName, fileContent) => { - const s3 = new AWS.S3(); +Cypress.Commands.add( + 'addFileToS3', + (bucketName: string, fileName: string, fileContent: AWS.S3.Body) => { + const s3 = new AWS.S3(); - const params: AWS.S3.Types.PutObjectRequest = { - Bucket: bucketName, - Key: fileName, - Body: fileContent, - }; + const params: AWS.S3.Types.PutObjectRequest = { + Bucket: bucketName, + Key: fileName, + Body: fileContent, + }; - s3.upload(params, (err, data) => { - if (err) { - console.error('Error uploading file to S3:', err); - } else { - console.log('File uploaded successfully to S3:', data.Location); - } - }); -}); + return cy.wrap( + new Cypress.Promise((resolve, reject) => { + s3.upload(params, (err, data) => { + if (err) { + const message = 'Error uploading file to S3:' + err; + console.error(message); + reject(message); + } else { + console.log('File uploaded successfully to S3:', data.Location); + resolve(data); + } + }); + }), + ); + }, +); -Cypress.Commands.add('addItemToDynamoDb', (tableName, item) => { - const dynamoDB = new AWS.DynamoDB(); +Cypress.Commands.add( + 'addItemToDynamoDb', + (tableName: string, item: AWS.DynamoDB.PutItemInputAttributeMap) => { + const dynamoDB = new AWS.DynamoDB(); - const params = { - TableName: tableName, - Item: AWS.DynamoDB.Converter.marshall(item), - }; + const params: AWS.DynamoDB.PutItemInput = { + TableName: tableName, + Item: AWS.DynamoDB.Converter.marshall(item), + }; - return cy.wrap(dynamoDB.putItem(params).promise(), { timeout: 10000 }); -}); + return cy.wrap( + new Cypress.Promise((resolve, reject) => { + dynamoDB.putItem(params, (err, data) => { + if (err) { + const message = 'Error uploading to Dynamo:' + tableName; + console.error(message); + reject(message); + } else { + console.log('Upload to Dynamo success:', tableName); + resolve(data); + } + }); + }), + ); + }, +); Cypress.Commands.add('deleteFileFromS3', (bucketName: string, fileName: string) => { const s3 = new AWS.S3(); @@ -39,9 +65,20 @@ Cypress.Commands.add('deleteFileFromS3', (bucketName: string, fileName: string) Key: fileName, }; - return cy.wrap(s3.deleteObject(params).promise(), { timeout: 10000 }).then(() => { - console.log('File deleted successfully from S3:', fileName); - }); + return cy.wrap( + new Cypress.Promise((resolve, reject) => { + s3.deleteObject(params, (err, data) => { + if (err) { + const message = 'Error uploading to S3:' + bucketName; + console.error(message); + reject(message); + } else { + console.log('Upload to S3 success:', bucketName); + resolve(data); + } + }); + }), + ); }); Cypress.Commands.add('deleteItemFromDynamoDb', (tableName: string, itemId: string) => { @@ -54,7 +91,18 @@ Cypress.Commands.add('deleteItemFromDynamoDb', (tableName: string, itemId: strin }, }; - return cy.wrap(dynamoDB.deleteItem(params).promise(), { timeout: 10000 }).then(() => { - console.log('Item deleted successfully from DynamoDB:', itemId); - }); + return cy.wrap( + new Cypress.Promise((resolve, reject) => { + dynamoDB.deleteItem(params, (err, data) => { + if (err) { + const message = 'Error uploading to Dynamo:' + tableName; + console.error(message); + reject(message); + } else { + console.log('Upload to Dynamo success:', tableName); + resolve(data); + } + }); + }), + ); }); diff --git a/app/cypress/support/aws.config.ts b/app/cypress/support/aws.config.ts index 225a34dde..1ec6ca0fe 100644 --- a/app/cypress/support/aws.config.ts +++ b/app/cypress/support/aws.config.ts @@ -2,10 +2,10 @@ import AWS from 'aws-sdk'; // need to get from env vars AWS.config.update({ - accessKeyId: '', - secretAccessKey: '', - region: '', - sessionToken: '', + accessKeyId: Cypress.env('AWS_accessKeyId'), + secretAccessKey: Cypress.env('AWS_secretAccessKey'), + region: Cypress.env('AWS_region'), + sessionToken: Cypress.env('AWS_sessionToken'), }); export default AWS; diff --git a/app/cypress/support/commands.ts b/app/cypress/support/commands.ts deleted file mode 100644 index 780b9dcbf..000000000 --- a/app/cypress/support/commands.ts +++ /dev/null @@ -1,39 +0,0 @@ -/// -const registerCypressGrep = require('@cypress/grep'); -registerCypressGrep(); -// *********************************************** -// 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 -// } -// } -// } diff --git a/app/cypress/support/e2e.ts b/app/cypress/support/e2e.ts index 2f552eb4b..5f186e92e 100644 --- a/app/cypress/support/e2e.ts +++ b/app/cypress/support/e2e.ts @@ -1,23 +1,9 @@ -/// -// *********************************************************** -// 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'; -import './aws.commands'; +import { DynamoDB, S3 } from 'aws-sdk'; import { Roles, roleIds, roleList } from './roles'; - +import Bluebird from 'cypress/types/bluebird'; +/// +const registerCypressGrep = require('@cypress/grep'); +registerCypressGrep(); Cypress.Commands.add('getByTestId', (selector, ...args) => { return cy.get(`[data-testid=${selector}]`, ...args); @@ -91,49 +77,59 @@ declare global { * @param {string} value - The value of the data-testid attribute of the target DOM element. * @return {HTMLElement} - Target DOM element. */ - getByTestId(value: string); + getByTestId(value: string): Chainable>; /** * Mock user login by intercepting the {baseUrl}/auth-callback request * @param {Roles} role - The user role to login with. Must be an enum of Roles */ - login(role: Roles); + login(role: Roles): Chainable; /** * Real user login via CIS2 and redirect back to {baseUrl}/auth-callback. * @param {Roles} role - The user role to login with. Must be an enum of Roles */ - smokeLogin(role: Roles); + smokeLogin(role: Roles): Chainable; /** * Add file to s3 bucket * @param {string} bucketName - Name of the target S3 bucket * @param {string} fileName - Filepath of the file to upload * @param {string} fileContent - Content of the file to upload + * @return {Promise} - S3 response for s3.upload */ addFileToS3( bucketName: string, fileName: string, - fileContent: string, - ): Chainable; + fileContent: S3.Body, + ): Chainable>; /** * Add dynamoDB entry * @param {string} tableName - Name of the target dynamoDB table * @param {{ [key: string]: any; }} item - dynamoDB item to upload + * @return {Promise} - Dynamo response for dynamoDB.putItem */ addItemToDynamoDb( tableName: string, - item: { [key: string]: string }, - ): Chainable; + item: DynamoDB.PutItemInputAttributeMap, + ): Chainable>; /** * Delete file from S3 bucket * @param {string} bucketName - Name of the target S3 bucket * @param {string} fileName - Filepath of the file to delete + * @return {Promise} - S3 response for s3.deleteObject */ - deleteFileFromS3(bucketName: string, fileName: string): Chainable; + deleteFileFromS3( + bucketName: string, + fileName: string, + ): Chainable>; /** * Delete item from DynamoDB table * @param {string} tableName - Name of the target DynamoDB table * @param {string} itemId - ID of the item to delete + * @return {Promise} - Dynamo response for dynamoDB.deleteItem */ - deleteItemFromDynamoDb(tableName: string, itemId: string): Chainable; + deleteItemFromDynamoDb( + tableName: string, + itemId: string, + ): Chainable>; } } } diff --git a/app/package-lock.json b/app/package-lock.json index 5a3fe060f..5328dbf09 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -13,7 +13,6 @@ "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "axios": "^1.5.0", - "cross-env": "^7.0.3", "dotenv": "^16.3.1", "eslint-plugin-legacy-decorators": "^1.0.0", "fake-progress": "^1.0.4", @@ -11694,23 +11693,6 @@ "node": ">=10" } }, - "node_modules/cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "bin": { - "cross-env": "src/bin/cross-env.js", - "cross-env-shell": "src/bin/cross-env-shell.js" - }, - "engines": { - "node": ">=10.14", - "npm": ">=6", - "yarn": ">=1" - } - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", diff --git a/app/package.json b/app/package.json index 97b533d8b..c6ed4e556 100644 --- a/app/package.json +++ b/app/package.json @@ -25,6 +25,7 @@ "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "aws-sdk": "^2.1510.0", "axios": "^1.5.0", "dotenv": "^16.3.1", "eslint-plugin-legacy-decorators": "^1.0.0", @@ -47,7 +48,6 @@ "web-vitals": "^2.1.4" }, "devDependencies": { - "aws-sdk": "^2.1510.0", "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@storybook/addon-essentials": "^7.4.0", "@storybook/addon-interactions": "^7.4.0", diff --git a/lambdas/services/bulk_upload_service.py b/lambdas/services/bulk_upload_service.py index edc632d41..82a628367 100644 --- a/lambdas/services/bulk_upload_service.py +++ b/lambdas/services/bulk_upload_service.py @@ -56,7 +56,7 @@ def process_message_queue(self, records: list): "All remaining messages in this batch will be returned to sqs queue to retry later." ) - all_unprocessed_message = records[index - 1:] + all_unprocessed_message = records[index - 1 :] for unprocessed_message in all_unprocessed_message: self.sqs_repository.put_sqs_message_back_to_queue( unprocessed_message