fix: isolate tests — each test only operates on its own resources

- milestone.spec.ts: use unique prefix 'Milestone Test Project', target
  project card by name, clean up (delete) project after verification
- project-editor.spec.ts: use unique prefix 'ProjEditor Test', target
  project card by name instead of first .project-card match

This prevents cross-test interference where project-editor would
accidentally delete the project created by the milestone test.
This commit is contained in:
zhi
2026-03-16 06:32:32 +00:00
parent 766f5ef33e
commit 5e3678ee67
2 changed files with 38 additions and 22 deletions

View File

@@ -59,7 +59,7 @@ test.describe('Milestone Editor', () => {
await page.waitForSelector('a:has-text("📁 Projects")', { timeout: 10000 }); await page.waitForSelector('a:has-text("📁 Projects")', { timeout: 10000 });
console.log('✅ Logged in'); console.log('✅ Logged in');
// Step 2: Create Project // Step 2: Create Project (unique name for this test)
console.log('📁 Creating project...'); console.log('📁 Creating project...');
await page.click('a:has-text("📁 Projects")'); await page.click('a:has-text("📁 Projects")');
await page.waitForLoadState('networkidle'); await page.waitForLoadState('networkidle');
@@ -68,7 +68,7 @@ test.describe('Milestone Editor', () => {
await page.click('button:has-text("+ New")'); await page.click('button:has-text("+ New")');
await page.waitForSelector('input[placeholder="Project name"]', { timeout: 10000 }); await page.waitForSelector('input[placeholder="Project name"]', { timeout: 10000 });
const projectName = 'Test Project ' + Date.now(); const projectName = 'Milestone Test Project ' + Date.now();
console.log('Creating project with name:', projectName); console.log('Creating project with name:', projectName);
await page.fill('input[placeholder="Project name"]', projectName); await page.fill('input[placeholder="Project name"]', projectName);
await page.fill('input[placeholder="Description (optional)"]', 'Project for milestone testing'); await page.fill('input[placeholder="Description (optional)"]', 'Project for milestone testing');
@@ -76,12 +76,13 @@ test.describe('Milestone Editor', () => {
await page.click('button:has-text("Create")'); await page.click('button:has-text("Create")');
await page.waitForTimeout(2000); await page.waitForTimeout(2000);
await page.waitForSelector('.project-card', { timeout: 10000 }); // Wait for our specific project card to appear
await page.waitForSelector(`.project-card:has-text("${projectName}")`, { timeout: 10000 });
console.log('✅ Project created'); console.log('✅ Project created');
// Step 3: Click on project to open it // Step 3: Click on OUR project to open it
console.log('👆 Opening project...'); console.log('👆 Opening project...');
await page.click('.project-card'); await page.click(`.project-card:has-text("${projectName}")`);
await page.waitForLoadState('networkidle'); await page.waitForLoadState('networkidle');
await page.waitForTimeout(1500); await page.waitForTimeout(1500);
console.log('✅ Project opened'); console.log('✅ Project opened');
@@ -134,6 +135,30 @@ test.describe('Milestone Editor', () => {
expect(hasMilestone).toBe(true); expect(hasMilestone).toBe(true);
console.log('✅ Milestone verified in UI'); console.log('✅ Milestone verified in UI');
// Step 6: Cleanup — delete the project we created
console.log('🧹 Cleaning up — deleting project...');
await page.click('a:has-text("📁 Projects")');
await page.waitForLoadState('networkidle');
await page.waitForSelector(`.project-card:has-text("${projectName}")`, { timeout: 10000 });
await page.click(`.project-card:has-text("${projectName}")`);
await page.waitForLoadState('networkidle');
await page.waitForTimeout(1000);
const deleteBtn = page.locator('button:has-text("Delete")');
if (await deleteBtn.isVisible().catch(() => false)) {
page.on('dialog', async dialog => {
const match = dialog.message().match(/Type the project name "(.*)" to confirm/);
if (match) {
await dialog.accept(match[1]);
} else {
await dialog.accept();
}
});
await deleteBtn.click();
await page.waitForTimeout(2000);
console.log('✅ Project cleaned up');
}
console.log('🎉 All milestone tests passed!'); console.log('🎉 All milestone tests passed!');
}); });
}); });

View File

@@ -44,7 +44,7 @@ test.describe('Project Editor', () => {
console.log('✅ Logged in'); console.log('✅ Logged in');
// Step 2: Create Project // Step 2: Create Project (unique name for this test)
console.log('📁 Creating project...'); console.log('📁 Creating project...');
// Click Projects in sidebar // Click Projects in sidebar
await page.click('a:has-text("📁 Projects")'); await page.click('a:has-text("📁 Projects")');
@@ -60,8 +60,8 @@ test.describe('Project Editor', () => {
// Wait for the form to appear (look for the project name input) // Wait for the form to appear (look for the project name input)
await page.waitForSelector('input[placeholder="Project name"]', { timeout: 10000 }); await page.waitForSelector('input[placeholder="Project name"]', { timeout: 10000 });
// Fill project form // Fill project form with a unique, identifiable name
const projectName = 'Test Project ' + Date.now(); const projectName = 'ProjEditor Test ' + Date.now();
console.log('Creating project with name:', projectName); console.log('Creating project with name:', projectName);
await page.fill('input[placeholder="Project name"]', projectName); await page.fill('input[placeholder="Project name"]', projectName);
await page.fill('input[placeholder="Description (optional)"]', 'Project for E2E testing'); await page.fill('input[placeholder="Description (optional)"]', 'Project for E2E testing');
@@ -72,23 +72,14 @@ test.describe('Project Editor', () => {
// Wait a bit for submission // Wait a bit for submission
await page.waitForTimeout(2000); await page.waitForTimeout(2000);
// Check if there are any errors in console // Wait for our specific project card to appear
const errors = await page.evaluate(() => { await page.waitForSelector(`.project-card:has-text("${projectName}")`, { timeout: 10000 });
return window.__errors || [];
});
if (errors.length > 0) {
console.log('Console errors:', errors);
}
// Wait for project to be created (and appear in the grid) - check for any project card
await page.waitForSelector('.project-card', { timeout: 10000 });
console.log('✅ Project created'); console.log('✅ Project created');
// Step 3: Delete the created project // Step 3: Delete the created project — click OUR project card by name
console.log('🗑️ Deleting project...'); console.log('🗑️ Deleting project...');
// Click on the project card to open it await page.click(`.project-card:has-text("${projectName}")`);
await page.click('.project-card');
await page.waitForLoadState('networkidle'); await page.waitForLoadState('networkidle');
await page.waitForTimeout(1000); await page.waitForTimeout(1000);
@@ -98,7 +89,7 @@ test.describe('Project Editor', () => {
console.log('Delete button visible:', deleteBtnVisible); console.log('Delete button visible:', deleteBtnVisible);
if (deleteBtnVisible) { if (deleteBtnVisible) {
// Set up prompt handler for the confirmation dialog - use dialog.defaultValue() to get the project name pattern // Set up prompt handler for the confirmation dialog
page.on('dialog', async dialog => { page.on('dialog', async dialog => {
console.log('Dialog message:', dialog.message()); console.log('Dialog message:', dialog.message());
// Extract project name from the message - format: "Type the project name "XXX" to confirm deletion:" // Extract project name from the message - format: "Type the project name "XXX" to confirm deletion:"