Skip to content

Commit 8cfabb6

Browse files
authored
PDF verification end-to-end test (#614)
* add package download fixture * click next recursively in test * refactor test * verify form field value exists * extract methods in test * reorder imports * update function signature
1 parent 92e145d commit 8cfabb6

5 files changed

Lines changed: 242 additions & 369 deletions

File tree

e2e/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
},
1111
"devDependencies": {
1212
"dotenv": "^16.4.7",
13-
"path-to-regexp": "^8.2.0"
13+
"path-to-regexp": "^8.2.0",
14+
"pdf-lib": "^1.17.1"
1415
},
1516
"dependencies": {
1617
"@gsa-tts/forms-common": "workspace:*"
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { test as base, expect } from './import-file.fixture';
2+
import { enLocale as message } from '@gsa-tts/forms-common';
3+
4+
export type AddPackageDownloadFixture = {
5+
formUrl: string;
6+
};
7+
8+
const test = base.extend<AddPackageDownloadFixture>({
9+
formUrl: async ({ page, formUrl }, use) => {
10+
await page.goto(formUrl);
11+
12+
await page.getByRole('button', { name: message.controls.addElement.textContent, exact: true }).click();
13+
await page
14+
.getByRole('button', { name: 'Page', exact: true })
15+
.click();
16+
await page
17+
.getByRole('link', { name: 'Untitled Page', exact: true })
18+
.click();
19+
20+
await page.getByRole('button', { name: message.controls.addElement.textContent, exact: true }).click();
21+
22+
await page
23+
.getByRole('button', { name: message.patterns.packageDownload.displayName })
24+
.click();
25+
26+
await page
27+
.getByRole('button', { name: 'Save and Close', exact: true })
28+
.click();
29+
30+
await page.waitForResponse((response) =>
31+
response.url().includes('/api/forms') && response.status() === 200,
32+
);
33+
34+
await page
35+
.getByRole('link', { name: 'Preview', exact: true })
36+
.click();
37+
38+
await use(formUrl);
39+
},
40+
});
41+
42+
export { test, expect };

e2e/src/form-filler.spec.ts

Lines changed: 84 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
import { test, expect } from './fixtures/import-file.fixture.js';
2-
import { FormFillerPage } from './models/form-filler-page.js';
1+
import fs from 'fs/promises';
32
import { match } from 'path-to-regexp';
3+
import { PDFDocument } from 'pdf-lib';
4+
import { test, expect } from './fixtures/add-download.fixture.js';
5+
import { FormFillerPage } from './models/form-filler-page.js';
46
import { Create } from '../../packages/design/src/FormManager/routes';
57

68
test.describe('Fill a form as an applicant', () => {
@@ -14,13 +16,13 @@ test.describe('Fill a form as an applicant', () => {
1416
}
1517

1618
return matcher(pagePath);
17-
}
19+
};
1820

1921
test('Next button navigation', async ({ page, formUrl }) => {
2022
const url = new URL(formUrl);
2123
const result = getFormParams(url);
2224

23-
if(result) {
25+
if (result) {
2426
const { formId } = result.params;
2527
const formPage = new FormFillerPage(page);
2628
await formPage.navigateTo(`${url.protocol}//${url.host}/forms/${formId}`);
@@ -39,7 +41,7 @@ test.describe('Fill a form as an applicant', () => {
3941
params.append('page', '2');
4042
const result = getFormParams(url);
4143

42-
if(result) {
44+
if (result) {
4345
const { formId } = result.params;
4446
const formPage = new FormFillerPage(page);
4547
await formPage.navigateTo(`${url.protocol}//${url.host}/forms/${formId}?${params.toString()}`);
@@ -51,4 +53,81 @@ test.describe('Fill a form as an applicant', () => {
5153
throw new Error('Invalid form URL');
5254
}
5355
});
56+
57+
test('Verify download', async ({ page, formUrl }) => {
58+
const url = new URL(formUrl);
59+
const result = getFormParams(url);
60+
const fields = [
61+
{ label: 'First Name', value: 'John' },
62+
{ label: 'Middle Name', value: 'Michael' },
63+
{ label: 'Last Name', value: 'Doe' },
64+
];
65+
66+
const getPdfFormFromFile = async (downloadPath: string) => {
67+
const pdfBuffer = await fs.readFile(downloadPath);
68+
const pdfDoc = await PDFDocument.load(pdfBuffer);
69+
return pdfDoc.getForm();
70+
}
71+
72+
const isFieldValuePresent = (pdfForm: PDFForm, fieldNames: string[], value: string) => {
73+
let fieldValueFound = false;
74+
for (const fieldName of fieldNames) {
75+
const pdfField = pdfForm.getField(fieldName);
76+
if (pdfField.getText() === value) {
77+
fieldValueFound = true;
78+
break;
79+
}
80+
}
81+
return fieldValueFound;
82+
}
83+
84+
if (result) {
85+
const { formId } = result.params;
86+
const formPage = new FormFillerPage(page);
87+
await formPage.navigateTo(`${url.protocol}//${url.host}/forms/${formId}`);
88+
89+
const isDownloadButtonVisible = async (): Promise<boolean> =>
90+
await page.getByRole('button', { name: 'Download PDF', exact: true }).isVisible();
91+
92+
const waitForDownloadButton = async () => {
93+
let isButtonVisible = await isDownloadButtonVisible();
94+
while (!isButtonVisible) {
95+
await formPage.clickNextButton();
96+
await page.waitForTimeout(500);
97+
isButtonVisible = await isDownloadButtonVisible();
98+
}
99+
};
100+
101+
for (const { label, value } of fields) {
102+
await formPage.updateInputValue(label, value);
103+
}
104+
105+
await waitForDownloadButton();
106+
107+
const downloadPromise = page.waitForEvent('download');
108+
await page.getByRole('button', { name: 'Download PDF', exact: true }).click();
109+
const download = await downloadPromise;
110+
expect(download.suggestedFilename()).toBe(
111+
'demo-application_for_certificate_of_pardon_for_simple_marijuana_possession.pdf',
112+
);
113+
114+
const downloadPath = await download.path();
115+
const pdfForm = await getPdfFormFromFile(downloadPath);
116+
const pdfFieldNames = pdfForm.getFields().map((pdfFormField) => pdfFormField.getName());
117+
118+
let fieldValuesFound = [];
119+
for (const { value } of fields) {
120+
fieldValuesFound = [
121+
...fieldValuesFound,
122+
isFieldValuePresent(pdfForm, pdfFieldNames, value)
123+
];
124+
}
125+
126+
expect(fieldValuesFound.every(value => value === true)).toBe(true);
127+
expect(fieldValuesFound.length).toBe(fields.length);
128+
129+
} else {
130+
throw new Error('Invalid form URL');
131+
}
132+
});
54133
});

e2e/src/models/form-filler-page.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,8 @@ export class FormFillerPage {
2121
await backButton.click();
2222
}
2323

24+
async updateInputValue(label, value) {
25+
await this.page.getByLabel(label).first().fill(value);
26+
}
27+
2428
}

0 commit comments

Comments
 (0)