import { test, expect } from '@playwright/test'; import { setupApiMocks, login, navigateTo, MOCK_CONTACTS } from './helpers'; test.describe('Contact CRUD E2E', () => { test.beforeEach(async ({ page }) => { await setupApiMocks(page); await login(page); }); test('create a new company contact', async ({ page }) => { await navigateTo(page, '/contacts'); // Wait for contacts page to load await expect(page.locator('[data-testid="contact-list-view"], [data-testid="contact-list-empty"], [data-testid="contact-list-loading"]')).toBeVisible({ timeout: 15_000 }); // Click the "new" toolbar button (Plus icon in plugin toolbar) const newBtn = page.locator('[data-testid="plugin-toolbar"] button').filter({ hasText: /new|neu|erstellen|create/i }).first(); await newBtn.click(); // Contact edit modal should appear await expect(page.locator('[data-testid="contact-type-select"]')).toBeVisible({ timeout: 10_000 }); // Select company type (should be default) await expect(page.locator('[data-testid="contact-name-input"]')).toBeVisible(); // Fill in company name await page.locator('[data-testid="contact-name-input"]').fill('Test Company GmbH'); // Fill in email await page.locator('input[type="email"]').first().fill('test@company.test'); // Submit await page.locator('[data-testid="contact-submit-btn"]').click(); // Modal should close (success) await expect(page.locator('[data-testid="contact-type-select"]')).not.toBeVisible({ timeout: 10_000 }); }); test('view contact detail and edit', async ({ page }) => { await navigateTo(page, '/contacts'); // Wait for list to load await expect(page.locator('[data-testid="contact-list-view"], [data-testid="contact-list-empty"]')).toBeVisible({ timeout: 15_000 }); // Click on first contact in the list const firstContact = page.locator('[data-testid="contact-list-view"] > div, [data-testid="contact-list-view"] button').first(); if (await firstContact.isVisible()) { await firstContact.click(); // Detail should appear await expect(page.locator('[data-testid="contact-detail"]')).toBeVisible({ timeout: 10_000 }); // Click edit button in detail const editBtn = page.locator('[data-testid="contact-detail"] button').filter({ hasText: /edit|bearbeiten/i }).first(); if (await editBtn.isVisible()) { await editBtn.click(); // Edit modal should appear await expect(page.locator('[data-testid="contact-type-select"]')).toBeVisible({ timeout: 10_000 }); // Modify name await page.locator('[data-testid="contact-name-input"]').fill('Updated Company GmbH'); // Save await page.locator('[data-testid="contact-submit-btn"]').click(); // Modal should close await expect(page.locator('[data-testid="contact-type-select"]')).not.toBeVisible({ timeout: 10_000 }); } } }); test('add ansprechpartner (contact person) to a company', async ({ page }) => { await navigateTo(page, '/contacts'); // Wait for list and click first contact await expect(page.locator('[data-testid="contact-list-view"], [data-testid="contact-list-empty"]')).toBeVisible({ timeout: 15_000 }); const firstContact = page.locator('[data-testid="contact-list-view"] > div, [data-testid="contact-list-view"] button').first(); if (await firstContact.isVisible()) { await firstContact.click(); await expect(page.locator('[data-testid="contact-detail"]')).toBeVisible({ timeout: 10_000 }); // Find and click "Add Person" button const addPersonBtn = page.locator('[data-testid="contact-detail"] button').filter({ hasText: /add.*person|ansprechpartner.*hinzuf/i }).first(); if (await addPersonBtn.isVisible()) { await addPersonBtn.click(); // Person modal should appear await expect(page.locator('[data-testid="person-save-btn"]')).toBeVisible({ timeout: 10_000 }); // Fill person details const inputs = page.locator('[data-testid="contact-detail"] input, .modal input, [role="dialog"] input'); const firstNameInput = inputs.nth(0); const lastNameInput = inputs.nth(1); await firstNameInput.fill('Anna'); await lastNameInput.fill('Schmidt'); // Save person await page.locator('[data-testid="person-save-btn"]').click(); // Modal should close await expect(page.locator('[data-testid="person-save-btn"]')).not.toBeVisible({ timeout: 10_000 }); } } }); test('delete a contact', async ({ page }) => { await navigateTo(page, '/contacts'); await expect(page.locator('[data-testid="contact-list-view"], [data-testid="contact-list-empty"]')).toBeVisible({ timeout: 15_000 }); const firstContact = page.locator('[data-testid="contact-list-view"] > div, [data-testid="contact-list-view"] button').first(); if (await firstContact.isVisible()) { await firstContact.click(); await expect(page.locator('[data-testid="contact-detail"]')).toBeVisible({ timeout: 10_000 }); // Set up confirm dialog handler page.on('dialog', (dialog) => dialog.accept()); // Click delete button const deleteBtn = page.locator('[data-testid="contact-detail"] button').filter({ hasText: /delete|löschen/i }).first(); if (await deleteBtn.isVisible()) { await deleteBtn.click(); // Detail should become empty after deletion await expect(page.locator('[data-testid="contact-detail-empty"], [data-testid="contact-detail-loading"]')).toBeVisible({ timeout: 10_000 }); } } }); });