Skip to content

Commit

Permalink
Error Alert Updates (#881)
Browse files Browse the repository at this point in the history
Closes #865

- Updated content of Alerts on Resolve errors (syntax + logic) pages
- Converted checkbox field level error to form level error on Warnings
page
- Added e2e tests for error Alerts
  • Loading branch information
ojbravo authored Sep 23, 2024
1 parent 7e77b1e commit 56e7bd3
Show file tree
Hide file tree
Showing 10 changed files with 378 additions and 72 deletions.
253 changes: 253 additions & 0 deletions e2e/pages/filing-app/formAlerts.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
import { expect } from '@playwright/test';
import { test } from '../../fixtures/testFixture';
import uploadFile from '../../utils/uploadFile';

test('Form Alerts', async ({
page,
navigateToProvideTypeOfFinancialInstitution,
}) => {
test.slow();

// Type of financial institution page
await test.step('Type of financial institution page', async () => {
navigateToProvideTypeOfFinancialInstitution;
await expect(page.locator('h1'), 'h1 is correct').toContainText(
'Provide type of financial institution',
);

// Submit Incomplete form
await test.step('Submit Incomplete form', async () => {
await test.step('Click: Continue', async () => {
await page.getByRole('button', { name: 'Continue' }).click();
});
await test.step('Error Alert is visible', async () => {
await page.waitForSelector('#TypesFinancialInstitutionsErrors', {
timeout: 10_000,
});
await expect(
page.locator(
'#TypesFinancialInstitutionsErrors div.m-notification_content',
),
'Alert is visible',
).toContainText(
'There was a problem updating your type of financial institution',
);
});
});

// Submit Completed Form
await test.step('Submit Completed form', async () => {
await test.step('Complete form', async () => {
await page.getByText('Bank or savings association').check();
});
await test.step('Click: Continue', async () => {
await page.getByRole('button', { name: 'Continue' }).click();
});
});
});

// Upload file with syntax errors
await test.step('Upload syntax errors file', async () => {
await uploadFile(page, true, 'syntax');

// Continue to next page
await test.step('Click: Continue', async () => {
await page.waitForSelector('#nav-next');
await page.waitForTimeout(500);
await page.getByRole('button', { name: 'Continue to next step' }).click();
});
});

// Resolve errors (syntax) page
await test.step('Resolve errors (syntax) page', async () => {
await expect(page.locator('h1'), 'h1 is correct').toContainText(
'Resolve errors (syntax)',
);
await expect(
page.locator('#error-header-alert'),
'Error alert is visible',
).toContainText(
'Your register contains syntax errorsThere may be an issue with the data type or format of one or more values in your file. Make sure your register meets the requirements detailed in the filing instructions guide (section 4, "Data validation"), make the corrections, and upload a new file.',
);
await test.step('Click: Continue', async () => {
await page
.getByRole('button', { name: 'Continue' })
.click({ timeout: 500 });
});

await expect(
page.locator('#error-footer-alert'),
'Footer alert is visible',
).toContainText('You must resolve syntax errors to continue.');

await test.step('Click: Upload new file', async () => {
await page.getByRole('link', { name: 'Upload a new file' }).click();
});
});

// Upload file with logic errors
await test.step('Upload logic errors file', async () => {
await uploadFile(page, false, 'logic');

// Continue to next page
await test.step('Click: Continue', async () => {
await page.waitForSelector('#nav-next');
await page.waitForTimeout(500);
await page.getByRole('button', { name: 'Continue to next step' }).click();
});
});

// Resolve errors (syntax) page
await test.step('Resolve errors (syntax) page', async () => {
await expect(page.locator('h1'), 'h1 is correct').toContainText(
'Resolve errors (syntax)',
);
await expect(
page.locator('.m-notification__success'),
'Success message is visible',
).toContainText('Your register contains no syntax errors');
await test.step('Click: Continue', async () => {
await page.getByRole('button', { name: 'Continue' }).click();
});
});

// Resolve errors (logic) page
await test.step('Resolve errors (logic) page', async () => {
await expect(page.locator('h1'), 'h1 is correct').toContainText(
'Resolve errors (logic)',
);
await expect(
page.locator('#error-header-alert'),
'Error alert is visible',
).toContainText(
'Your register contains logic errorsThere is missing data, incorrect data, or conflicting information in your file. Make sure your register meets the requirements detailed in the filing instructions guide (section 4, "Data validation"), make the corrections, and upload a new file.',
);
await test.step('Click: Continue', async () => {
await page
.getByRole('button', { name: 'Continue to next step' })
.click({ timeout: 500 });
});

await expect(
page.locator('#error-footer-alert'),
'Footer alert is visible',
).toContainText(
'You must resolve all errors to continue to the next step.',
);
await test.step('Click: Upload new file', async () => {
await page.getByRole('link', { name: 'Upload a new file' }).click();
});
});

// Upload file with warnings
await test.step('Upload warnings file', async () => {
await uploadFile(page, false, 'warning');

await test.step('Click: Continue', async () => {
await page
.getByRole('button', { name: 'Continue to next step' })
.click({ timeout: 5000 });
});
});

// Resolve errors (syntax) page
await test.step('Resolve errors (syntax) page', async () => {
await expect(page.locator('h1'), 'h1 is correct').toContainText(
'Resolve errors (syntax)',
);
await expect(
page.locator('.m-notification__success'),
'Success message is visible',
).toContainText('Your register contains no syntax errors');

await test.step('Click: Continue', async () => {
await page
.getByRole('button', { name: 'Continue' })
.click({ timeout: 5000 });
});
});

// Resolve errors (logic) page
await test.step('Resolve errors (logic) page', async () => {
await expect(page.locator('h1'), 'h1 is correct').toContainText(
'Resolve errors (logic)',
);
await expect(
page.locator('.m-notification__success'),
'Success message is visible',
).toContainText('Your register contains no logic errors');
await test.step('Click: Continue', async () => {
await page
.getByRole('button', { name: 'Continue to next step' })
.click({ timeout: 5000 });
});
});

// Review warnings page
await test.step('Review warnings page', async () => {
await expect(page.locator('h1'), 'h1 is correct').toContainText(
'Review warnings',
);
await test.step('Click: Continue', async () => {
await page.getByRole('button', { name: 'Continue to next step' }).click();
});
await expect(
page.locator('#error-header-alert'),
'Error alert is visible',
).toContainText(
'You must correct or verify the accuracy of register values to continue to the next step.',
);
await test.step('Click: Verify checkbox', async () => {
await page.getByText('I verify the accuracy of').check({ timeout: 500 });
});
await test.step('Click: Continue', async () => {
await page.getByRole('button', { name: 'Continue to next step' }).click();
});
});

// Point of contact page
await test.step('Point of contact page', async () => {
await expect(page.locator('h1'), 'h1 is correct').toContainText(
'Provide point of contact',
);

// Submit Incomplete form
await test.step('Submit Incomplete form', async () => {
await test.step('Click: Continue', async () => {
await page
.getByRole('button', { name: 'Continue to next step' })
.click();
});
await expect(
page.locator('.m-notification__error'),
'Error alert is visible',
).toContainText(
'There was a problem updating your point of contact informationEnter the first name of the point of contactEnter the last name of the point of contactEnter the phone number of the point of contactEnter the email address of the point of contactEnter the street address of the point of contactEnter the city of the point of contactSelect the state or territory of the point of contactEnter the ZIP code of the point of contact',
);
});

// Submit Completed form
await test.step('Submit Completed form', async () => {
await test.step('Complete form', async () => {
await page.getByLabel('First name').fill('Playwright');
await page.getByLabel('Last name').fill('Test');
await page.getByLabel('Work phone').fill('555-555-5555');
await page.getByLabel('Email address').fill('playwright@test.com');
await page.getByLabel('Street address line 1').fill('555 Main St.');
await page.getByLabel('City').fill('Utah (U');
await page.selectOption('select#state', 'UT');
await page.getByLabel('Zip code').fill('55555');
});
});
await test.step('Click: Continue', async () => {
await page.getByRole('button', { name: 'Continue to next step' }).click();
});
});

// Sign and submit page
await test.step('Sign and submit page', async () => {
await expect(page.locator('h1'), 'h1 is correct').toContainText(
'Sign and submit',
);
});
});
4 changes: 4 additions & 0 deletions e2e/test-data/sample-sblar-files/errors-page-1-syntax-few.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
uid,app_date,app_method,app_recipient,ct_credit_product,ct_credit_product_ff,ct_guarantee,ct_guarantee_ff,ct_loan_term_flag,ct_loan_term,credit_purpose,credit_purpose_ff,amount_applied_for_flag,amount_applied_for,amount_approved,action_taken,action_taken_date,denial_reasons,denial_reasons_ff,pricing_interest_rate_type,pricing_init_rate_period,pricing_fixed_rate,pricing_adj_margin,pricing_adj_index_name,pricing_adj_index_name_ff,pricing_adj_index_value,pricing_origination_charges,pricing_broker_fees,pricing_initial_charges,pricing_mca_addcost_flag,pricing_mca_addcost,pricing_prepenalty_allowed,pricing_prepenalty_exists,census_tract_adr_type,census_tract_number,gross_annual_revenue_flag,gross_annual_revenue,naics_code_flag,naics_code,number_of_workers,time_in_business_type,time_in_business,business_ownership_status,num_principal_owners_flag,num_principal_owners,po_1_ethnicity,po_1_ethnicity_ff,po_1_race,po_1_race_anai_ff,po_1_race_asian_ff,po_1_race_baa_ff,po_1_race_pi_ff,po_1_gender_flag,po_1_gender_ff,po_2_ethnicity,po_2_ethnicity_ff,po_2_race,po_2_race_anai_ff,po_2_race_asian_ff,po_2_race_baa_ff,po_2_race_pi_ff,po_2_gender_flag,po_2_gender_ff,po_3_ethnicity,po_3_ethnicity_ff,po_3_race,po_3_race_anai_ff,po_3_race_asian_ff,po_3_race_baa_ff,po_3_race_pi_ff,po_3_gender_flag,po_3_gender_ff,po_4_ethnicity,po_4_ethnicity_ff,po_4_race,po_4_race_anai_ff,po_4_race_asian_ff,po_4_race_baa_ff,po_4_race_pi_ff,po_4_gender_flag,po_4_gender_ff
000TESTFIUIDDONOTUSEXBXVID451XTC1,20241201,1,1,988,,999,,999,,999,,999,,,5,20241231,999,,999,,,,999,,,,,,999,,999,999,988,,988,,988,,988,988,,988,900,9001,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
000TESTFIUIDDONOTUSEXBXVID452XTC1,20241201,1,1,988,,999,,999,,999,,999,,,5,20241231,999,,999,,,,999,,,,,,999,,999,999,988,,988,,988,,988,988,,988,988,must be blank,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
000TESTFIUIDDONOTUSEXBXVID21XTC2,12012024,1,1,988,,999,,999,,999,,999,,,5,20241231,999,,999,,,,999,,,,,,999,,999,999,988,,988,,988,,988,988,,988,988,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
4 changes: 4 additions & 0 deletions e2e/test-data/sample-sblar-files/errors-page-2-logic-few.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
uid,app_date,app_method,app_recipient,ct_credit_product,ct_credit_product_ff,ct_guarantee,ct_guarantee_ff,ct_loan_term_flag,ct_loan_term,credit_purpose,credit_purpose_ff,amount_applied_for_flag,amount_applied_for,amount_approved,action_taken,action_taken_date,denial_reasons,denial_reasons_ff,pricing_interest_rate_type,pricing_init_rate_period,pricing_fixed_rate,pricing_adj_margin,pricing_adj_index_name,pricing_adj_index_name_ff,pricing_adj_index_value,pricing_origination_charges,pricing_broker_fees,pricing_initial_charges,pricing_mca_addcost_flag,pricing_mca_addcost,pricing_prepenalty_allowed,pricing_prepenalty_exists,census_tract_adr_type,census_tract_number,gross_annual_revenue_flag,gross_annual_revenue,naics_code_flag,naics_code,number_of_workers,time_in_business_type,time_in_business,business_ownership_status,num_principal_owners_flag,num_principal_owners,po_1_ethnicity,po_1_ethnicity_ff,po_1_race,po_1_race_anai_ff,po_1_race_asian_ff,po_1_race_baa_ff,po_1_race_pi_ff,po_1_gender_flag,po_1_gender_ff,po_2_ethnicity,po_2_ethnicity_ff,po_2_race,po_2_race_anai_ff,po_2_race_asian_ff,po_2_race_baa_ff,po_2_race_pi_ff,po_2_gender_flag,po_2_gender_ff,po_3_ethnicity,po_3_ethnicity_ff,po_3_race,po_3_race_anai_ff,po_3_race_asian_ff,po_3_race_baa_ff,po_3_race_pi_ff,po_3_gender_flag,po_3_gender_ff,po_4_ethnicity,po_4_ethnicity_ff,po_4_race,po_4_race_anai_ff,po_4_race_asian_ff,po_4_race_baa_ff,po_4_race_pi_ff,po_4_gender_flag,po_4_gender_ff
123456789TESTBANK12300001,20201201,1,1,988,test,999;999;999;999;999;999,test,988,0,999;999;999;999,test,999,0,0,3,20241031,999;999;999;999;999,test,5,,0,,999,test,0,,,,900,,999,999,988,01001020100,988,0,988,1234,988,988,0,988;988,900,0,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
123456789TESTBANK12300001,20241201,1,1,988,test,999;999;999;999;999;999,test,988,0,999;999;999;999,test,999,0,0,1,20201231,977,,5,,0,,999,test,0,,,,900,,999,999,988,01001020100,988,0,988,1234,988,988,0,988;988,900,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
123456789TESTBANK12300001,20241201,1,1,988,test,999;999;999;999;999;999,test,988,0,999;999;999;999,test,999,0,0,1,20201231,977,,5,0,0,,999,test,0,,,,900,,999,999,988,01001020100,988,0,988,1234,988,988,0,988;988,900,4,966;966,test,966;966,test,test,test,test,,test,966;966,test,966;966,test,test,test,test,,test,966;966,test,966;966,test,test,test,test,,test,966;966,test,966;966,test,test,test,test,,test
3 changes: 3 additions & 0 deletions e2e/test-data/sample-sblar-files/warnings-page-few.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
uid,app_date,app_method,app_recipient,ct_credit_product,ct_credit_product_ff,ct_guarantee,ct_guarantee_ff,ct_loan_term_flag,ct_loan_term,credit_purpose,credit_purpose_ff,amount_applied_for_flag,amount_applied_for,amount_approved,action_taken,action_taken_date,denial_reasons,denial_reasons_ff,pricing_interest_rate_type,pricing_init_rate_period,pricing_fixed_rate,pricing_adj_margin,pricing_adj_index_name,pricing_adj_index_name_ff,pricing_adj_index_value,pricing_origination_charges,pricing_broker_fees,pricing_initial_charges,pricing_mca_addcost_flag,pricing_mca_addcost,pricing_prepenalty_allowed,pricing_prepenalty_exists,census_tract_adr_type,census_tract_number,gross_annual_revenue_flag,gross_annual_revenue,naics_code_flag,naics_code,number_of_workers,time_in_business_type,time_in_business,business_ownership_status,num_principal_owners_flag,num_principal_owners,po_1_ethnicity,po_1_ethnicity_ff,po_1_race,po_1_race_anai_ff,po_1_race_asian_ff,po_1_race_baa_ff,po_1_race_pi_ff,po_1_gender_flag,po_1_gender_ff,po_2_ethnicity,po_2_ethnicity_ff,po_2_race,po_2_race_anai_ff,po_2_race_asian_ff,po_2_race_baa_ff,po_2_race_pi_ff,po_2_gender_flag,po_2_gender_ff,po_3_ethnicity,po_3_ethnicity_ff,po_3_race,po_3_race_anai_ff,po_3_race_asian_ff,po_3_race_baa_ff,po_3_race_pi_ff,po_3_gender_flag,po_3_gender_ff,po_4_ethnicity,po_4_ethnicity_ff,po_4_race,po_4_race_anai_ff,po_4_race_asian_ff,po_4_race_baa_ff,po_4_race_pi_ff,po_4_gender_flag,po_4_gender_ff
000TESTFIUIDDONOTUSEXGXVID11XTC1,20241201,1,1,988,,999,,999,,999,,999,,,5,20241231,999,,999,,,,999,,,,,,999,,999,999,988,,988,,988,,988,988,,988,988,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
000TESTFIUIDDONOTUSEXGXVID12XTC1,20241201,1,1,1,,999,,900,1300,999,,999,,,5,20241231,999,,999,,,,999,,,,,,999,,999,999,988,,988,,988,,988,988,,988,988,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
13 changes: 6 additions & 7 deletions src/components/AlertApiUnavailable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,31 @@ import type { ComponentProps } from 'react';
import { sblHelpMail } from 'utils/common';

interface AlertApiUnavailableProperties {
message: string;
// eslint-disable-next-line react/require-default-props
message?: string;
// eslint-disable-next-line react/require-default-props
href?: string;
}
/**
* For use when an API call fails
*/
export function AlertApiUnavailable({
message,
message = 'Unable to connect at the moment',
href = sblHelpMail,
...others
}: AlertApiUnavailableProperties & ComponentProps<typeof Alert>): JSX.Element {
return (
<Alert
className='mb-[2.8125rem] [&_div]:max-w-[41.875rem] [&_p]:max-w-[41.875rem]'
className='u-mt45 mx-auto mb-[2.8125rem] [&_div]:max-w-[41.875rem] [&_p]:max-w-[41.875rem]'
message={message}
status='error'
aria-live='polite'
aria-atomic='true'
{...others}
>
<Paragraph>
There was a connection issue or our service may be temporarily
unavailable. Make sure your computer is connected to the internet, and
try again. If this issue persists,{' '}
<Link href={href}>contact our support staff</Link>.
Try again in a few minutes. If this issue persists,{' '}
<Link href={href}>email our support staff</Link>.
</Paragraph>
</Alert>
);
Expand Down
40 changes: 37 additions & 3 deletions src/pages/Filing/FilingApp/FilingErrors/FilingErrorsAlerts.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Link } from 'components/Link';
import { Alert, Paragraph } from 'design-system-react';
import { Alert, Link, Paragraph } from 'design-system-react';
import { ValidationInitialFetchFailAlert } from 'pages/Filing/FilingApp/FileSubmission.data';
import { dataValidationLink } from 'utils/common';

Expand All @@ -14,7 +13,6 @@ function SuccessAlert({ isStep2 }: { isStep2: boolean }): JSX.Element {
/>
);
}

function SyntaxErrorsAlert(): JSX.Element {
return (
<Alert
Expand Down Expand Up @@ -57,12 +55,48 @@ function LogicErrorsAlert(): JSX.Element {
);
}

function SyntaxErrorsAlertFooter(): JSX.Element {
return (
<Alert
className='mb-[2.8125rem] [&_div]:max-w-[41.875rem] [&_p]:max-w-[41.875rem]'
message='You must resolve syntax errors to continue.'
status='error'
id='error-footer-alert'
/>
);
}

function LogicErrorsAlertFooter(): JSX.Element {
return (
<Alert
className='mb-[2.8125rem] [&_div]:max-w-[41.875rem] [&_p]:max-w-[41.875rem]'
message='You must resolve all errors to continue to the next step.'
status='error'
id='error-footer-alert'
/>
);
}

interface FilingErrorsAlertsProperties {
isStep2: boolean;
errorState: boolean;
errorGetSubmissionLatest: unknown;
}

export function FilingErrorsAlertsFooter({
isStep2,
errorState,
errorGetSubmissionLatest,
}: FilingErrorsAlertsProperties): JSX.Element | null {
return errorGetSubmissionLatest ? (
<ValidationInitialFetchFailAlert />
) : errorState && isStep2 ? (
<LogicErrorsAlertFooter />
) : errorState && !isStep2 ? (
<SyntaxErrorsAlertFooter />
) : null;
}

function FilingErrorsAlerts({
isStep2,
errorState,
Expand Down
Loading

0 comments on commit 56e7bd3

Please sign in to comment.