42b19040ce
- playwright.config.ts: chromium project, webServer, baseURL, trace/screenshot/video - e2e/helpers.ts: API mock setup, login/logout helpers, mock data for all entities - 7 E2E spec files (1164 lines total): - auth.spec.ts: login/logout workflow - contact-crud.spec.ts: create/edit/delete contacts, add persons - search.spec.ts: global search, filter, results - plugin-toggle.spec.ts: enable/disable plugins, UI changes - mail.spec.ts: mail account setup, folders, mail viewing - dms.spec.ts: folder creation, file upload, preview, share - calendar.spec.ts: appointment creation, calendar switch, kanban view - @playwright/test added as devDependency - e2e scripts added to package.json - TSC: 0 new errors (only pre-existing Dms.tsx)
133 lines
5.5 KiB
TypeScript
133 lines
5.5 KiB
TypeScript
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 });
|
|
}
|
|
}
|
|
});
|
|
});
|