diff --git a/integration-tests/tests/pages/submission.page.ts b/integration-tests/tests/pages/submission.page.ts index 02f71bc10b..24d7dbed9c 100644 --- a/integration-tests/tests/pages/submission.page.ts +++ b/integration-tests/tests/pages/submission.page.ts @@ -268,4 +268,108 @@ export class BulkSubmissionPage extends SubmissionPage { }), ); } + + /** + * Complete a bulk submission with N sequences using the same or different metadata/sequences. + * + * @param options.count - Number of sequences to submit (when using identical data) + * @param options.metadata - Array of metadata objects for each sequence, or a single object to replicate + * @param options.sequenceData - Array of sequence data objects, or a single object to replicate + * @param options.groupId - Optional group ID to submit to a specific group + * @param options.isRestricted - Whether to use restricted data terms (default: false) + * @returns ReviewPage after submission completes + */ + async completeBulkSubmission({ + count, + metadata, + sequenceData, + groupId, + isRestricted = false, + }: { + count?: number; + metadata: + | { + submissionId: string; + collectionCountry: string; + collectionDate: string; + authorAffiliations: string; + } + | Array<{ + submissionId: string; + collectionCountry: string; + collectionDate: string; + authorAffiliations: string; + }>; + sequenceData: Record | Array>; + groupId?: string | number; + isRestricted?: boolean; + }): Promise { + // Determine the actual count + const actualCount = Array.isArray(metadata) + ? metadata.length + : Array.isArray(sequenceData) + ? sequenceData.length + : (count ?? 1); + + // Normalize metadata to array + const finalMetadata: Array<{ + submissionId: string; + collectionCountry: string; + collectionDate: string; + authorAffiliations: string; + }> = Array.isArray(metadata) + ? metadata + : Array.from({ length: actualCount }, (_, i) => ({ + ...metadata, + submissionId: `${metadata.submissionId}-${i}`, + })); + + // Normalize sequenceData to array + const finalSequenceData: Array> = Array.isArray(sequenceData) + ? sequenceData + : Array.from({ length: actualCount }, () => ({ ...sequenceData })); + + if (groupId) { + await this.page.goto(`/ebola-sudan/submission/${groupId}/submit`); + } else { + await this.navigateToSubmissionPage(); + } + + // Upload metadata + const headers = [ + 'submissionId', + 'collectionCountry', + 'collectionDate', + 'authorAffiliations', + ]; + const rows = finalMetadata.map((m) => [ + m.submissionId, + m.collectionCountry, + m.collectionDate, + m.authorAffiliations, + ]); + await this.uploadMetadataFile(headers, rows); + + // Upload sequences - create FASTA with submission IDs as headers + const sequenceMap: Record = {}; + for (let i = 0; i < actualCount; i++) { + const seqData = finalSequenceData[i]; + // For single-segment organisms, use just the submission ID + // For multi-segment, we need to handle the segment names + for (const [segmentName, sequence] of Object.entries(seqData)) { + const header = + segmentName === 'main' + ? finalMetadata[i].submissionId + : `${finalMetadata[i].submissionId}_${segmentName}`; + sequenceMap[header] = sequence; + } + } + await this.uploadSequencesFile(sequenceMap); + + if (isRestricted) { + await this.selectRestrictedDataUseTerms(); + } + + return this.submitAndWaitForProcessingDone(); + } } diff --git a/integration-tests/tests/specs/features/review-page.spec.ts b/integration-tests/tests/specs/features/review-page.spec.ts index 18f5797344..318d3b880c 100644 --- a/integration-tests/tests/specs/features/review-page.spec.ts +++ b/integration-tests/tests/specs/features/review-page.spec.ts @@ -1,7 +1,7 @@ import { expect } from '@playwright/test'; import { test } from '../../fixtures/group.fixture'; import { ReviewPage } from '../../pages/review.page'; -import { SingleSequenceSubmissionPage } from '../../pages/submission.page'; +import { BulkSubmissionPage, SingleSequenceSubmissionPage } from '../../pages/submission.page'; import { createTestMetadata, createTestSequenceData } from '../../test-helpers/test-data'; test.describe('Review page functionality', () => { @@ -27,12 +27,15 @@ test.describe('Review page functionality', () => { test('should allow bulk approval of sequences', async ({ page, groupId }) => { test.setTimeout(120_000); - const submissionPage = new SingleSequenceSubmissionPage(page); + const submissionPage = new BulkSubmissionPage(page); - // Submit 3 sequences to test bulk operations properly - for (let i = 0; i < 3; i++) { - await submissionPage.completeSubmission(createTestMetadata(), createTestSequenceData()); - } + // Use bulk submission for efficiency + await submissionPage.completeBulkSubmission({ + count: 3, + metadata: createTestMetadata(), + sequenceData: createTestSequenceData(), + groupId, + }); const reviewPage = new ReviewPage(page); await reviewPage.goto(groupId); @@ -50,12 +53,15 @@ test.describe('Review page functionality', () => { test('should allow bulk discarding of sequences', async ({ page, groupId }) => { test.setTimeout(120_000); - const submissionPage = new SingleSequenceSubmissionPage(page); - - // Submit 3 sequences to test bulk operations properly - for (let i = 0; i < 3; i++) { - await submissionPage.completeSubmission(createTestMetadata(), createTestSequenceData()); - } + const submissionPage = new BulkSubmissionPage(page); + + // Use bulk submission for efficiency + await submissionPage.completeBulkSubmission({ + count: 3, + metadata: createTestMetadata(), + sequenceData: createTestSequenceData(), + groupId, + }); const reviewPage = new ReviewPage(page); await reviewPage.goto(groupId); diff --git a/integration-tests/tests/specs/features/revise-sequence.spec.ts b/integration-tests/tests/specs/features/revise-sequence.spec.ts index c7689bc3f1..6fa6dbcf16 100644 --- a/integration-tests/tests/specs/features/revise-sequence.spec.ts +++ b/integration-tests/tests/specs/features/revise-sequence.spec.ts @@ -5,7 +5,7 @@ import { SearchPage } from '../../pages/search.page'; import { ReviewPage } from '../../pages/review.page'; import { RevisionPage } from '../../pages/revision.page'; import { NavigationPage } from '../../pages/navigation.page'; -import { SingleSequenceSubmissionPage } from '../../pages/submission.page'; +import { BulkSubmissionPage } from '../../pages/submission.page'; import { CCHF_S_SEGMENT_FULL_SEQUENCE, createFastaContent, @@ -71,16 +71,16 @@ groupTest.describe('Bulk sequence revision', () => { groupTest('can revise multiple sequences via file upload', async ({ page, groupId }) => { groupTest.setTimeout(200_000); - const submissionPage = new SingleSequenceSubmissionPage(page); + const submissionPage = new BulkSubmissionPage(page); const timestamp = Date.now(); - // TODO #5524 Optimize by using bulk submission instead of 3 sequential single submissions - for (let i = 0; i < SEQUENCES_TO_REVISE; i++) { - await submissionPage.completeSubmission( - createTestMetadata({ submissionId: `bulk-revise-${timestamp}-${i}` }), - createTestSequenceData(), - ); - } + // Use bulk submission instead of sequential single submissions for efficiency + await submissionPage.completeBulkSubmission({ + count: SEQUENCES_TO_REVISE, + metadata: createTestMetadata({ submissionId: `bulk-revise-${timestamp}` }), + sequenceData: createTestSequenceData(), + groupId, + }); const reviewPage = new ReviewPage(page); await reviewPage.goto(groupId);