Skip to content

Commit ffaf7ec

Browse files
committed
SW-7641 Make playwright tests run in parallel
1 parent 093b206 commit ffaf7ec

25 files changed

+261
-375
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"pre-commit": "yarn format && yarn lint && yarn ts && yarn test && yarn build",
3333
"playwright:run": "yarn run playwright test playwright/e2e",
3434
"playwright:debug": "yarn run playwright test playwright/e2e --debug",
35-
"playwright:demo": "SLOW_MO=750 yarn run playwright test playwright/e2e --headed",
35+
"playwright:demo": "SLOW_MO=750 TIMEOUT=600000 yarn run playwright test playwright/e2e --headed",
3636
"test:e2e": "NODE_OPTIONS=--max-old-space-size=16384 REACT_APP_TERRAWARE_TIER=test start-server-and-test start http://127.0.0.1:3000 playwright:run",
3737
"dump:local": "./scripts/dump.sh local",
3838
"dump:docker": "./scripts/dump.sh docker",

playwright.config.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,12 @@ export default defineConfig({
1414
// Folder for test artifacts such as screenshots, videos, traces, etc.
1515
outputDir: './playwright/test-results',
1616

17-
/* Run tests in files in parallel */
18-
fullyParallel: true,
1917
/* Fail the build on CI if you accidentally left test.only in the source code. */
2018
forbidOnly: !!process.env.CI,
2119
/* Retry on CI only */
2220
retries: process.env.CI ? 2 : 0,
2321
/* Opt out of parallel tests. */
24-
workers: 1,
22+
workers: process.env.CI ? 2 : 4,
2523
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
2624
reporter: 'html',
2725
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
@@ -34,7 +32,7 @@ export default defineConfig({
3432
slowMo: parseInt(process.env.SLOW_MO || '0'),
3533
},
3634
},
37-
testMatch: 'test.list.ts',
35+
timeout: 60000,
3836

3937
/* Configure projects for major browsers */
4038
projects: process.env.CI
Lines changed: 127 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
import { expect, test } from '@playwright/test';
22

33
import { changeToSuperAdmin } from '../utils/userUtils';
4-
import { exactOptions, waitFor } from '../utils/utils';
5-
6-
test.setTimeout(60000);
7-
test.beforeEach(async ({ context }, testInfo) => {
8-
await changeToSuperAdmin(context);
9-
});
4+
import { exactOptions, selectOrg, waitFor } from '../utils/utils';
105

116
const yearId = new Date().getFullYear().toString().slice(-2);
12-
let accessionId = 'UNSET';
13-
let accessionRow = 'UNSET';
147

15-
export default function AccessionTests() {
16-
test('Add An Accession', async ({ page }, testInfo) => {
17-
await page.goto('http://127.0.0.1:3000');
8+
test.describe('AccessionTests', () => {
9+
// Skip the withdraw tests if the first test fails (Add An Accession)
10+
test.describe.configure({ mode: 'serial' });
1811

12+
let accessionId = 'UNSET';
13+
test.beforeEach(async ({ page, context }, testInfo) => {
14+
await changeToSuperAdmin(context);
15+
await page.goto('http://127.0.0.1:3000');
1916
await waitFor(page, '#home');
17+
await selectOrg(page, 'Terraformation (staging)');
18+
});
2019

20+
test('Add An Accession', async ({ page }, testInfo) => {
2121
await page.getByRole('button', { name: 'Seeds' }).click();
2222
await page.getByRole('button', { name: 'Accessions' }).click();
2323
await page.getByRole('button', { name: 'Add Accession' }).click();
@@ -112,7 +112,7 @@ export default function AccessionTests() {
112112

113113
await page.getByRole('button', { name: 'Accessions' }).click();
114114

115-
accessionRow = (
115+
const accessionRow = (
116116
await page
117117
.getByText(accessionId)
118118
.locator('../..')
@@ -124,101 +124,119 @@ export default function AccessionTests() {
124124
await expect(page.getByRole('main')).toContainText('Coconut');
125125
});
126126

127-
test('Withdraw to Nursery by seed count', async ({ page }, testInfo) => {
128-
await page.goto('http://127.0.0.1:3000');
129-
130-
await waitFor(page, '#home');
131-
132-
await page.getByRole('button', { name: 'Seeds' }).click();
133-
await page.getByRole('button', { name: 'Accessions' }).click();
134-
await page.locator(`#${accessionRow}-accessionNumber`).getByText(accessionId).click();
135-
await page.getByRole('button', { name: 'Withdraw' }).click();
136-
await page.locator('#destinationFacilityId').getByRole('textbox').click();
137-
await page.getByText('Nursery', exactOptions).nth(0).click();
138-
await page.getByLabel('Seed Count', exactOptions).check();
139-
await page.locator('#withdrawnQuantity').getByRole('textbox').fill('300');
140-
await page.getByRole('button', { name: 'Add Notes' }).click();
141-
await page.locator('textarea').fill('Adding some test notes here!');
142-
await page.locator('#saveWithdraw').click();
143-
await expect(page.getByRole('main')).toContainText('195 Grams');
144-
await expect(page.getByRole('main')).toContainText('~195 ct');
145-
await page.getByRole('tab', { name: 'History' }).click();
146-
await expect(page.getByLabel('History')).toContainText(
147-
'Super Admin withdrew 300 seeds for nurseryAdding some test notes here!'
148-
);
149-
await page.getByRole('button', { name: 'Seedlings' }).click();
150-
await page.getByRole('button', { name: 'Inventory', ...exactOptions }).click();
151-
await expect(page.locator('#row1-species_scientificName')).toContainText('Coconut');
152-
await expect(page.locator('#row1-facilityInventories')).toContainText('Nursery');
153-
await expect(page.locator('#row1-germinatingQuantity')).toContainText('300');
154-
await page.getByRole('tab', { name: 'By Nursery' }).click();
155-
await expect(page.locator('#row1-facility_name')).toContainText('Nursery');
156-
await page.getByRole('tab', { name: 'By Batch' }).click();
157-
await expect(page.locator('#row1-batchNumber')).toContainText('2-1-002');
158-
});
159-
160-
test('Withdraw to Outplant', async ({ page }, testInfo) => {
161-
await page.goto('http://127.0.0.1:3000');
162-
163-
await waitFor(page, '#home');
164-
165-
await page.getByRole('button', { name: 'Seeds' }).click();
166-
await page.getByRole('button', { name: 'Accessions' }).click();
167-
await page.locator(`#${accessionRow}-accessionNumber`).getByText(accessionId).click();
168-
await page.getByRole('button', { name: 'Withdraw' }).click();
169-
170-
await page.getByPlaceholder('Select...').first().click();
171-
await page.getByText('Out-planting').click();
172-
await page.getByLabel('Seed Count', { exact: true }).check();
173-
await page.locator('#withdrawnQuantity').getByRole('textbox').fill('100');
174-
await page.locator('#saveWithdraw').click();
175-
await expect(page.getByRole('main')).toContainText('95 Grams');
176-
await expect(page.getByRole('main')).toContainText('~95 ct');
177-
});
178-
179-
test('Withdraw to Viability Test', async ({ page }, testInfo) => {
180-
await page.goto('http://127.0.0.1:3000');
181-
182-
await waitFor(page, '#home');
183-
184-
await page.getByRole('button', { name: 'Seeds' }).click();
185-
await page.getByRole('button', { name: 'Accessions' }).click();
186-
await page.locator(`#${accessionRow}-accessionNumber`).getByText(accessionId).click();
187-
await page.getByRole('button', { name: 'Withdraw' }).click();
188-
await page.locator('.textfield-value > .tw-icon > path').first().click();
189-
await page.getByText('Viability Testing').click();
190-
await page.getByPlaceholder('Select...').nth(1).click();
191-
await page.getByText('Nursery').click();
192-
await page.locator('div:nth-child(3) > .select > .textfield-container > .textfield-value').click();
193-
await page.getByText('Soil').click();
194-
await page.getByPlaceholder('Select...').nth(3).click();
195-
await page.getByText('Soak').click();
196-
await page.locator('#withdrawnQuantity').getByRole('spinbutton').fill('20');
197-
await page.locator('#saveWithdraw').click();
198-
await expect(page.getByRole('main')).toContainText('75 Grams');
199-
await expect(page.getByRole('main')).toContainText('~75 ct');
200-
await page.getByRole('tab', { name: 'Viability Tests' }).click();
201-
await expect(page.locator('#row1-testType')).toContainText('Nursery Germination');
202-
await page.getByRole('table', { name: 'enhanced table' }).getByRole('img').click();
203-
await expect(page.getByRole('main')).toContainText('Viability Result: Pending');
204-
await expect(page.getByRole('main')).toContainText('Soil');
205-
await expect(page.getByRole('main')).toContainText('Soak');
206-
await expect(page.getByRole('main')).toContainText('20');
207-
await page.getByRole('button', { name: 'Edit' }).click();
208-
await page.getByPlaceholder('Select...').nth(1).click();
209-
await page.getByText('Fresh').click();
210-
await page.getByRole('button', { name: 'Add Observation' }).click();
211-
await page.locator('#seedsGerminated').getByRole('textbox').fill('15');
212-
await page.getByRole('button', { name: 'Save' }).click();
213-
await page.waitForTimeout(1000); //Wait for modal to close
214-
await page.locator('#row1-viabilityPercent').click();
215-
await expect(page.getByRole('main')).toContainText('15');
216-
await page.getByRole('button', { name: 'Edit' }).click();
217-
await page.getByRole('button', { name: 'Add Observation' }).click();
218-
await page.locator('div:nth-child(3) > div:nth-child(2) > div > .textfield > #seedsGerminated > input').fill('3');
219-
await page.getByLabel('Mark as Complete').check();
220-
await page.getByRole('button', { name: 'Save' }).click();
221-
await page.getByRole('button', { name: 'Apply Result' }).click();
222-
await expect(page.locator('#row1-viabilityPercent')).toContainText('90%');
127+
test.describe('Withdraw Tests', () => {
128+
test.describe.configure({ mode: 'default' });
129+
test('Withdraw to Nursery by seed count', async ({ page }, testInfo) => {
130+
await page.getByRole('button', { name: 'Seeds' }).click();
131+
await page.getByRole('button', { name: 'Accessions' }).click();
132+
133+
const accessionRow = (
134+
await page
135+
.getByText(accessionId)
136+
.locator('../..')
137+
.evaluate((el) => el.id)
138+
).replace('-accessionNumber', '');
139+
await page.locator(`#${accessionRow}-accessionNumber`).getByText(accessionId).click();
140+
await page.getByRole('button', { name: 'Withdraw' }).click();
141+
await page.locator('#destinationFacilityId').getByRole('textbox').click();
142+
await page.getByText('Nursery', exactOptions).nth(0).click();
143+
await page.getByLabel('Seed Count', exactOptions).check();
144+
await page.locator('#withdrawnQuantity').getByRole('textbox').fill('300');
145+
await page.getByRole('button', { name: 'Add Notes' }).click();
146+
await page.locator('textarea').fill('Adding some test notes here!');
147+
await page.locator('#saveWithdraw').click();
148+
await expect(page.getByRole('main')).toContainText('195 Grams');
149+
await expect(page.getByRole('main')).toContainText('~195 ct');
150+
await page.getByRole('tab', { name: 'History' }).click();
151+
await expect(page.getByLabel('History')).toContainText(
152+
'Super Admin withdrew 300 seeds for nurseryAdding some test notes here!'
153+
);
154+
await page.getByRole('button', { name: 'Seedlings' }).click();
155+
await page.getByRole('button', { name: 'Inventory', ...exactOptions }).click();
156+
const coconutRowNum = (
157+
await page
158+
.getByText('Coconut', exactOptions)
159+
.locator('../..')
160+
.evaluate((el) => el.id)
161+
).replace('-species_scientificName', '');
162+
await expect(page.locator(`#${coconutRowNum}-species_scientificName`)).toContainText('Coconut');
163+
await expect(page.locator(`#${coconutRowNum}-facilityInventories`)).toContainText('Nursery');
164+
await expect(page.locator(`#${coconutRowNum}-germinatingQuantity`)).toContainText('300');
165+
await page.getByRole('tab', { name: 'By Nursery' }).click();
166+
await expect(page.locator('#row1-facility_name')).toContainText('Nursery');
167+
await page.getByRole('tab', { name: 'By Batch' }).click();
168+
await expect(page.locator('#row1-batchNumber')).toContainText('2-1-002');
169+
});
170+
171+
test('Withdraw to Outplant', async ({ page }, testInfo) => {
172+
await page.getByRole('button', { name: 'Seeds' }).click();
173+
await page.getByRole('button', { name: 'Accessions' }).click();
174+
175+
const accessionRow = (
176+
await page
177+
.getByText(accessionId)
178+
.locator('../..')
179+
.evaluate((el) => el.id)
180+
).replace('-accessionNumber', '');
181+
await page.locator(`#${accessionRow}-accessionNumber`).getByText(accessionId).click();
182+
await page.getByRole('button', { name: 'Withdraw' }).click();
183+
184+
await page.getByPlaceholder('Select...').first().click();
185+
await page.getByText('Out-planting').click();
186+
await page.getByLabel('Seed Count', { exact: true }).check();
187+
await page.locator('#withdrawnQuantity').getByRole('textbox').fill('100');
188+
await page.locator('#saveWithdraw').click();
189+
await expect(page.getByRole('main')).toContainText('95 Grams');
190+
await expect(page.getByRole('main')).toContainText('~95 ct');
191+
});
192+
193+
test('Withdraw to Viability Test', async ({ page }, testInfo) => {
194+
await page.getByRole('button', { name: 'Seeds' }).click();
195+
await page.getByRole('button', { name: 'Accessions' }).click();
196+
197+
const accessionRow = (
198+
await page
199+
.getByText(accessionId)
200+
.locator('../..')
201+
.evaluate((el) => el.id)
202+
).replace('-accessionNumber', '');
203+
await page.locator(`#${accessionRow}-accessionNumber`).getByText(accessionId).click();
204+
await page.getByRole('button', { name: 'Withdraw' }).click();
205+
await page.locator('.textfield-value > .tw-icon > path').first().click();
206+
await page.getByText('Viability Testing').click();
207+
await page.getByPlaceholder('Select...').nth(1).click();
208+
await page.getByText('Nursery').click();
209+
await page.locator('div:nth-child(3) > .select > .textfield-container > .textfield-value').click();
210+
await page.getByText('Soil').click();
211+
await page.getByPlaceholder('Select...').nth(3).click();
212+
await page.getByText('Soak').click();
213+
await page.locator('#withdrawnQuantity').getByRole('spinbutton').fill('20');
214+
await page.locator('#saveWithdraw').click();
215+
await expect(page.getByRole('main')).toContainText('75 Grams');
216+
await expect(page.getByRole('main')).toContainText('~75 ct');
217+
await page.getByRole('tab', { name: 'Viability Tests' }).click();
218+
await expect(page.locator('#row1-testType')).toContainText('Nursery Germination');
219+
await page.getByRole('table', { name: 'enhanced table' }).getByRole('img').click();
220+
await expect(page.getByRole('main')).toContainText('Viability Result: Pending');
221+
await expect(page.getByRole('main')).toContainText('Soil');
222+
await expect(page.getByRole('main')).toContainText('Soak');
223+
await expect(page.getByRole('main')).toContainText('20');
224+
await page.getByRole('button', { name: 'Edit' }).click();
225+
await page.getByPlaceholder('Select...').nth(1).click();
226+
await page.getByText('Fresh').click();
227+
await page.getByRole('button', { name: 'Add Observation' }).click();
228+
await page.locator('#seedsGerminated').getByRole('textbox').fill('15');
229+
await page.getByRole('button', { name: 'Save' }).click();
230+
await page.waitForTimeout(1000); //Wait for modal to close
231+
await page.locator('#row1-viabilityPercent').click();
232+
await expect(page.getByRole('main')).toContainText('15');
233+
await page.getByRole('button', { name: 'Edit' }).click();
234+
await page.getByRole('button', { name: 'Add Observation' }).click();
235+
await page.locator('div:nth-child(3) > div:nth-child(2) > div > .textfield > #seedsGerminated > input').fill('3');
236+
await page.getByLabel('Mark as Complete').check();
237+
await page.getByRole('button', { name: 'Save' }).click();
238+
await page.getByRole('button', { name: 'Apply Result' }).click();
239+
await expect(page.locator('#row1-viabilityPercent')).toContainText('90%');
240+
});
223241
});
224-
}
242+
});

playwright/e2e/suites/deliverables.spec.ts

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,17 @@ import {
3434
verifyHomepageDeliverableStatus,
3535
} from '../utils/participantDeliverable';
3636
import { changeToContributor, changeToReadOnlyUser, changeToSuperAdmin } from '../utils/userUtils';
37-
import { exactOptions, waitFor } from '../utils/utils';
37+
import { exactOptions, selectOrg, waitFor } from '../utils/utils';
3838

39-
test.beforeEach(async ({ context }) => {
40-
await changeToSuperAdmin(context);
41-
});
42-
43-
export default function DeliverableTests() {
44-
test('Deliverables tab shows up once cohort has module with deliverables', async ({ page, context }) => {
39+
test.describe('DeliverableTests', () => {
40+
test.beforeEach(async ({ page, context }) => {
41+
await changeToSuperAdmin(context);
4542
await page.goto('http://127.0.0.1:3000');
4643
await waitFor(page, '#home');
44+
await selectOrg(page, 'Terraformation (staging)');
45+
});
4746

47+
test('Deliverables tab shows up once cohort has module with deliverables', async ({ page, context }) => {
4848
const today = new Date();
4949
const tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000);
5050

@@ -83,9 +83,6 @@ export default function DeliverableTests() {
8383
});
8484

8585
test('Questionnaire Deliverable', async ({ page }) => {
86-
await page.goto('http://127.0.0.1:3000');
87-
await waitFor(page, '#home');
88-
8986
const deliverableName = 'Phase 1 Questions';
9087
const today = new Date();
9188
const todayString = today.toISOString().split('T')[0];
@@ -293,9 +290,6 @@ export default function DeliverableTests() {
293290
});
294291

295292
test('Species Deliverable', async ({ page }) => {
296-
await page.goto('http://127.0.0.1:3000');
297-
await waitFor(page, '#home');
298-
299293
const deliverableName = 'Phase 1 Species';
300294
await verifyHomepageDeliverableStatus(deliverableName, 'Incomplete', true, 'Not Submitted', page);
301295
await page.getByText('Deliverables', exactOptions).click();
@@ -355,4 +349,4 @@ export default function DeliverableTests() {
355349
await validateSpeciesStatus('Banana', 'Update Needed', page);
356350
await validateSpeciesStatus('Kousa Dogwood', 'Approved', page);
357351
});
358-
}
352+
});

playwright/e2e/suites/funderProjectProfile.spec.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ import { test } from '@playwright/test';
33
import { ProjectDetails, publishProjectProfile, validateProjectProfilePage } from '../utils/projectProfile';
44
import { changeToFunderUser, changeToSuperAdmin } from '../utils/userUtils';
55

6-
test.setTimeout(20000);
7-
8-
export default function FunderProjectProfileTests() {
6+
test.describe('FunderProjectProfileTests', () => {
97
test('Publish Project and then View Published Project', async ({ page, context }, testInfo) => {
108
// publish project
119
await changeToSuperAdmin(context);
@@ -52,4 +50,4 @@ export default function FunderProjectProfileTests() {
5250

5351
await validateProjectProfilePage(projectDetails, page);
5452
});
55-
}
53+
});

0 commit comments

Comments
 (0)