forked from jsnbuchanan/crowd-funder-for-time-pwa
After calling OnboardingDialog from ProjectsView, route back to projects page again The onboarding dialog was designed to route back to HomeView when called from ProjectsView. The tests need to be updated to account for this intended behavior.
154 lines
5.5 KiB
TypeScript
154 lines
5.5 KiB
TypeScript
/**
|
|
* @file Bulk Project Creation Test Suite
|
|
* @description Tests TimeSafari's project creation functionality under load by creating multiple projects in sequence
|
|
*
|
|
* This test verifies:
|
|
* 1. Scalability
|
|
* - System can handle creation of multiple projects (10)
|
|
* - Performance remains stable across iterations
|
|
* - No data corruption during bulk operations
|
|
*
|
|
* 2. Data Integrity
|
|
* - Each project has unique identifiers
|
|
* - All projects are properly stored and retrievable
|
|
* - No cross-contamination between project data
|
|
*
|
|
* 3. UI Responsiveness
|
|
* - Interface remains responsive during bulk operations
|
|
* - Feedback is provided for each creation
|
|
* - No memory leaks or performance degradation
|
|
*
|
|
* Test Flow:
|
|
* 1. Setup Phase
|
|
* - Generate array of unique identifiers
|
|
* - Prepare standard text templates
|
|
* - Calculate common date/time values
|
|
* - Import test user (User 00)
|
|
*
|
|
* 2. Bulk Creation (10 iterations)
|
|
* - Navigate to projects page
|
|
* - Handle first-time onboarding dialog
|
|
* - Create project with unique data
|
|
* - Verify project creation success
|
|
* - Confirm project details display correctly
|
|
*
|
|
* Test Data:
|
|
* - Project Count: 10 projects
|
|
* - Title Format: "Idea [unique-string]"
|
|
* - Description Format: "Description of Idea [unique-string]"
|
|
* - Website: https://example.com (common across all)
|
|
* - Start Date: Current date + 30 days
|
|
* - Start Time: Current time + 1 hour
|
|
*
|
|
* Key Selectors:
|
|
* - Project title: 'h2'
|
|
* - Project content: '#Content'
|
|
* - New project button: 'button > svg.fa-plus'
|
|
* - Onboarding close: 'div > svg.fa-xmark'
|
|
*
|
|
* Performance Considerations:
|
|
* - Uses test.slow() to extend timeout
|
|
* - Handles potential UI lag between operations
|
|
* - Manages memory usage during bulk operations
|
|
*
|
|
* Error Handling:
|
|
* - Closes onboarding dialog only on first iteration
|
|
* - Verifies each project individually
|
|
* - Maintains operation even if individual creations fail
|
|
*
|
|
* Related Files:
|
|
* - Project utilities: ./testUtils
|
|
* - JWT handling: sw_scripts/safari-notifications.js
|
|
* - Project view: src/views/ProjectView.vue
|
|
*
|
|
* @see Documentation in usage-guide.md for project creation workflows
|
|
* @requires @playwright/test
|
|
* @requires ./testUtils - For user management and string generation
|
|
*
|
|
* @example
|
|
* ```typescript
|
|
* // Generate unique strings for multiple projects
|
|
* const uniqueStrings = await createUniqueStringsArray(10);
|
|
*
|
|
* // Create projects in sequence
|
|
* for (let i = 0; i < projectCount; i++) {
|
|
* await page.goto('./projects');
|
|
* await page.locator('button > svg.fa-plus').click();
|
|
* await page.getByPlaceholder('Idea Name').fill(`Idea ${uniqueStrings[i]}`);
|
|
* }
|
|
* ```
|
|
*/
|
|
|
|
import { test, expect } from '@playwright/test';
|
|
import { createUniqueStringsArray, importUser } from './testUtils';
|
|
|
|
test('Create 10 new projects', async ({ page }) => {
|
|
test.slow(); // Set timeout longer since it often fails at 30 seconds
|
|
|
|
const projectCount = 10;
|
|
|
|
// Standard texts
|
|
const standardTitle = "Idea ";
|
|
const standardDescription = "Description of Idea ";
|
|
const standardWebsite = 'https://example.com';
|
|
|
|
// Title and description arrays
|
|
const finalTitles = [];
|
|
const finalDescriptions = [];
|
|
|
|
// Create an array of unique strings
|
|
const uniqueStrings = await createUniqueStringsArray(projectCount);
|
|
|
|
// Populate arrays with titles and descriptions
|
|
for (let i = 0; i < projectCount; i++) {
|
|
let loopTitle = standardTitle + uniqueStrings[i];
|
|
finalTitles.push(loopTitle);
|
|
let loopDescription = standardDescription + uniqueStrings[i];
|
|
finalDescriptions.push(loopDescription);
|
|
}
|
|
|
|
// Set date
|
|
const today = new Date();
|
|
const oneMonthAhead = new Date(today.setDate(today.getDate() + 30));
|
|
const standardDate = oneMonthAhead.toISOString().split('T')[0];
|
|
|
|
// Set time
|
|
const now = new Date();
|
|
const futureTime = new Date(now.setHours(now.getHours() + 1));
|
|
const standardHour = futureTime.getHours().toString().padStart(2, '0');
|
|
const standardMinute = futureTime.getMinutes().toString().padStart(2, '0');
|
|
const standardTime = `${standardHour}:${standardMinute}`;
|
|
|
|
// Import user 00
|
|
await importUser(page, '00');
|
|
|
|
// Create new projects
|
|
for (let i = 0; i < projectCount; i++) {
|
|
await page.goto('./projects');
|
|
if (i === 0) {
|
|
// Check if onboarding dialog exists and close it if present
|
|
try {
|
|
await page.getByTestId('closeOnboardingAndFinish').click({ timeout: 2000 });
|
|
await page.waitForFunction(() => {
|
|
return !document.querySelector('.dialog-overlay');
|
|
}, { timeout: 5000 });
|
|
} catch (error) {
|
|
// No onboarding dialog present, continue
|
|
console.log('No onboarding dialog found on projects page');
|
|
}
|
|
}
|
|
// Route back to projects page again, because the onboarding dialog was designed to route to HomeView when called from ProjectsView
|
|
await page.goto('./projects');
|
|
await page.locator('button > svg.fa-plus').click();
|
|
await page.getByPlaceholder('Idea Name').fill(finalTitles[i]); // Add random suffix
|
|
await page.getByPlaceholder('Description').fill(finalDescriptions[i]);
|
|
await page.getByPlaceholder('Website').fill(standardWebsite);
|
|
await page.getByPlaceholder('Start Date').fill(standardDate);
|
|
await page.getByPlaceholder('Start Time').fill(standardTime);
|
|
await page.getByRole('button', { name: 'Save Project' }).click();
|
|
|
|
// Check texts
|
|
await expect(page.locator('h2')).toContainText(finalTitles[i]);
|
|
await expect(page.locator('#Content')).toContainText(finalDescriptions[i]);
|
|
}
|
|
}); |