import { test, expect } from '@playwright/test'; // Test 1: Navigate to first editable (non-finalized) service edit page test('navigate to first editable service edit page', async ({ page }) => { await page.goto('/services'); await page.waitForLoadState('networkidle'); // Find first unfinalized service (one with edit button) const editButton = page.getByTestId('service-list-edit-button').first(); const hasEditableService = await editButton.isVisible().catch(() => false); if (!hasEditableService) { test.skip(); } // Click edit button await editButton.click(); await page.waitForLoadState('networkidle'); // Verify we're on the edit page await expect(page).toHaveURL(/.*services\/\d+\/edit/); // Verify Information block is visible const informationBlock = page.getByTestId('information-block'); await expect(informationBlock).toBeVisible(); }); test('information block is always visible without accordion toggle', async ({ page }) => { await page.goto('/services'); await page.waitForLoadState('networkidle'); const editButton = page.getByTestId('service-list-edit-button').first(); const hasEditableService = await editButton.isVisible().catch(() => false); if (!hasEditableService) { test.skip(); } await editButton.click(); await page.waitForLoadState('networkidle'); const informationBlock = page.getByTestId('information-block'); await expect(informationBlock).toBeVisible(); const blockToggles = page.getByTestId('service-edit-block-toggle'); const toggleCount = await blockToggles.count(); expect(toggleCount).toBe(0); }); // Test 3: Upload area is visible with drag-and-drop zone and click-to-upload test('upload area is visible with drag-and-drop zone', async ({ page }) => { await page.goto('/services'); await page.waitForLoadState('networkidle'); // Find first unfinalized service const editButton = page.getByTestId('service-list-edit-button').first(); const hasEditableService = await editButton.isVisible().catch(() => false); if (!hasEditableService) { test.skip(); } await editButton.click(); await page.waitForLoadState('networkidle'); // Verify Information block uploader is visible const uploader = page.getByTestId('information-block-uploader'); await expect(uploader).toBeVisible(); // Verify dropzone is visible const dropzone = page.getByTestId('slide-uploader-dropzone'); await expect(dropzone).toBeVisible(); // Verify dropzone contains expected text await expect(dropzone).toContainText('Dateien hier ablegen'); await expect(dropzone).toContainText('oder klicken zum Auswählen'); }); // Test 4: Expire date input is visible for information slides test('expire date input is visible for information slides', async ({ page }) => { await page.goto('/services'); await page.waitForLoadState('networkidle'); // Find first unfinalized service const editButton = page.getByTestId('service-list-edit-button').first(); const hasEditableService = await editButton.isVisible().catch(() => false); if (!hasEditableService) { test.skip(); } await editButton.click(); await page.waitForLoadState('networkidle'); // Verify expire date input is visible const expireInput = page.getByTestId('slide-uploader-expire-input'); await expect(expireInput).toBeVisible(); // Verify it's a date input const inputType = await expireInput.getAttribute('type'); expect(inputType).toBe('date'); }); // Test 5: Existing slides display as thumbnails with expire date fields test('existing slides display as thumbnails with expire date fields', async ({ page }) => { await page.goto('/services'); await page.waitForLoadState('networkidle'); // Find first unfinalized service const editButton = page.getByTestId('service-list-edit-button').first(); const hasEditableService = await editButton.isVisible().catch(() => false); if (!hasEditableService) { test.skip(); } await editButton.click(); await page.waitForLoadState('networkidle'); // Verify slide grid is visible const slideGrid = page.getByTestId('information-block-grid'); await expect(slideGrid).toBeVisible(); // Check if slides exist const slideThumbnails = page.locator('[data-testid="slide-grid-delete-button"]'); const slideCount = await slideThumbnails.count(); if (slideCount === 0) { // No slides exist - verify empty state message const emptyState = slideGrid.locator('text=Noch keine Folien vorhanden'); await expect(emptyState).toBeVisible(); return; } // Slides exist - verify first thumbnail is visible const firstThumbnail = page.locator('[data-testid="slide-grid-delete-button"]').first(); await expect(firstThumbnail).toBeVisible(); // Verify delete button is visible on hover const deleteButton = firstThumbnail; await expect(deleteButton).toBeVisible(); }); // Test 6: Datepicker for expire date is functional test('datepicker for expire date is functional', async ({ page }) => { await page.goto('/services'); await page.waitForLoadState('networkidle'); // Find first unfinalized service const editButton = page.getByTestId('service-list-edit-button').first(); const hasEditableService = await editButton.isVisible().catch(() => false); if (!hasEditableService) { test.skip(); } await editButton.click(); await page.waitForLoadState('networkidle'); // Check if slides exist const slideThumbnails = page.locator('[data-testid="slide-grid-delete-button"]'); const slideCount = await slideThumbnails.count(); if (slideCount === 0) { // No slides exist - skip this test test.skip(); } // Find first slide's expire date input const expireInputs = page.locator('[data-testid="slide-grid-expire-input"]'); const firstExpireInput = expireInputs.first(); const expireInputExists = await firstExpireInput.isVisible().catch(() => false); if (!expireInputExists) { // Expire date field not in edit mode - click to enable edit const expireDateDisplay = page.locator('[data-testid="slide-grid-delete-button"]').first().locator('xpath=ancestor::div[@class*="slide-card"]').locator('text=/\\d{2}\\.\\d{2}\\.\\d{4}|Kein Ablaufdatum/').first(); const displayExists = await expireDateDisplay.isVisible().catch(() => false); if (!displayExists) { test.skip(); } // Click on the expire date display to enter edit mode await expireDateDisplay.click(); await page.waitForTimeout(200); } // Verify expire date input is now visible const expireInput = page.locator('[data-testid="slide-grid-expire-input"]').first(); await expect(expireInput).toBeVisible(); // Set a date value const futureDate = new Date(); futureDate.setDate(futureDate.getDate() + 30); const dateString = futureDate.toISOString().split('T')[0]; await expireInput.fill(dateString); // Verify the value was set const inputValue = await expireInput.inputValue(); expect(inputValue).toBe(dateString); // Verify save button is visible const saveButton = page.getByTestId('slide-grid-expire-save').first(); await expect(saveButton).toBeVisible(); }); // Test 7: Delete button on slide thumbnail triggers confirmation test('delete button on slide thumbnail triggers confirmation', async ({ page }) => { await page.goto('/services'); await page.waitForLoadState('networkidle'); // Find first unfinalized service const editButton = page.getByTestId('service-list-edit-button').first(); const hasEditableService = await editButton.isVisible().catch(() => false); if (!hasEditableService) { test.skip(); } await editButton.click(); await page.waitForLoadState('networkidle'); // Check if slides exist const slideThumbnails = page.locator('[data-testid="slide-grid-delete-button"]'); const slideCount = await slideThumbnails.count(); if (slideCount === 0) { // No slides exist - skip this test test.skip(); } // Get first delete button const firstDeleteButton = page.getByTestId('slide-grid-delete-button').first(); await expect(firstDeleteButton).toBeVisible(); // Click delete button await firstDeleteButton.click(); await page.waitForTimeout(200); // Verify confirmation dialog appears const confirmDialog = page.locator('text=Folie löschen?'); await expect(confirmDialog).toBeVisible(); // Verify dialog contains expected text await expect(page.locator('text=Möchtest du die Folie')).toBeVisible(); await expect(page.locator('text=wirklich löschen?')).toBeVisible(); // Verify cancel button is visible const cancelButton = page.locator('button:has-text("Abbrechen")').first(); await expect(cancelButton).toBeVisible(); // Click cancel to close dialog without deleting await cancelButton.click(); await page.waitForTimeout(200); // Verify dialog is closed const dialogClosed = await confirmDialog.isHidden().catch(() => true); expect(dialogClosed).toBe(true); });