
This commit includes several improvements and new features: - Updated the WebSocket connection logic in `websocket.py` to include connection status messages and periodic pings for maintaining the connection. - Introduced new skeleton components (`Skeleton.vue`, `SkeletonDashboard.vue`, `SkeletonList.vue`) for improved loading states in the UI, enhancing user experience during data fetching. - Refactored the Vite configuration to support advanced code splitting and caching strategies, optimizing the build process. - Enhanced ESLint configuration for better compatibility with project structure. These changes aim to improve real-time communication, user interface responsiveness, and overall application performance.
120 lines
6.6 KiB
TypeScript
120 lines
6.6 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
const BASE_URL = 'http://localhost:5173'; // Assuming Vite's default dev server URL
|
|
|
|
// Credentials - These should ideally come from a shared config or be set by a global setup.
|
|
// For this example, we'll assume the user from auth.spec.ts exists or we use a known test user.
|
|
// If auth.spec.ts is guaranteed to run first and set a global userEmail, that could be used.
|
|
// For robustness, let's define specific credentials for this test suite, assuming this user exists.
|
|
// Or, better, use a dynamic user from auth.spec.ts if possible or a global setup.
|
|
// For now, hardcoding for clarity, but this implies this user MUST exist.
|
|
const userEmailForGroupTests = `testuser_${process.env.PLAYWRIGHT_WORKER_INDEX || 0}@example.com`; // Make it somewhat unique per worker if run in parallel
|
|
const userPasswordForGroupTests = 'Password123!';
|
|
|
|
// Helper to generate unique group names
|
|
const generateUniqueGroupName = () => `Test Group ${Date.now()}`;
|
|
let currentGroupName = ''; // To store the name of the group created in the test
|
|
|
|
test.describe.configure({ mode: 'serial' }); // Run group tests serially
|
|
|
|
// --- Login before all tests in this suite ---
|
|
test.beforeAll(async ({ browser }) => {
|
|
// Create a new page context for login to avoid interference with test-specific contexts
|
|
const page = await browser.newPage();
|
|
await page.goto(`${BASE_URL}/auth/login`);
|
|
await page.locator('input#email').fill(userEmailForGroupTests);
|
|
await page.locator('input#password').fill(userPasswordForGroupTests);
|
|
await page.locator('form button[type="submit"]:has-text("Login")').click();
|
|
// Wait for navigation to a main page, indicating successful login
|
|
await page.waitForURL(new RegExp(`${BASE_URL}/(chores|groups|dashboard)?/?$`));
|
|
// Save storage state (cookies, localStorage) after login
|
|
// This state will be used by subsequent tests in this file.
|
|
await page.context().storageState({ path: `e2e/.auth/user-${process.env.PLAYWRIGHT_WORKER_INDEX || 0}.json` });
|
|
await page.close();
|
|
});
|
|
|
|
// Use the saved authentication state for all tests in this file
|
|
test.use({ storageState: `e2e/.auth/user-${process.env.PLAYWRIGHT_WORKER_INDEX || 0}.json` });
|
|
|
|
|
|
test('1. Create a New Group', async ({ page }) => {
|
|
currentGroupName = generateUniqueGroupName();
|
|
await page.goto(`${BASE_URL}/groups`); // Assuming /groups is the main groups page
|
|
|
|
// Updated "Create New Group" button selector
|
|
const createGroupButton = page.getByRole('button', { name: 'Create New Group' })
|
|
.or(page.locator('.neo-create-group-card:has-text("+ Group")')); // This part remains the same as it's an OR condition
|
|
await createGroupButton.click();
|
|
|
|
// Updated modal input for group name selector
|
|
await page.locator('input#newGroupNameInput').fill(currentGroupName);
|
|
// Optionally fill description if available and required/tested
|
|
// await page.locator('textarea#group-description').fill('This is a test group description.');
|
|
|
|
// Updated modal submit button selector
|
|
await page.locator('.modal-footer').getByRole('button', { name: 'Create' }).click();
|
|
|
|
// Verify success notification (adjust selector for your notification component)
|
|
const successNotification = page.locator('.notification.success, .alert.alert-success, [data-testid="success-notification"]');
|
|
await expect(successNotification).toBeVisible({ timeout: 10000 });
|
|
await expect(successNotification).toContainText(/Group created successfully|Group saved successfully/i);
|
|
|
|
|
|
// Verify that the new group appears in the list of groups on the page
|
|
// Adjust selector for group items and how group name is displayed
|
|
await expect(page.locator(`:text("${currentGroupName}")`).first()).toBeVisible();
|
|
// More specific: await expect(page.locator(`.group-list-item:has-text("${currentGroupName}")`)).toBeVisible();
|
|
});
|
|
|
|
test('2. View Group Details', async ({ page }) => {
|
|
await page.goto(`${BASE_URL}/groups`);
|
|
|
|
// Click on the group created in the previous test to navigate to its detail page
|
|
// Updated group card selector (using :has-text for specificity) and group name header (h1.neo-group-header)
|
|
const groupCard = page.locator(`.neo-group-card:has-text("${currentGroupName}")`);
|
|
// The h1.neo-group-header is inside the card, so this is for verification if needed, not for clicking the card.
|
|
// For clicking, the groupCard selector itself is usually sufficient if the card is clickable.
|
|
await groupCard.click();
|
|
|
|
// Verify redirection to the group detail page (URL might be like /groups/some-id)
|
|
await page.waitForURL(new RegExp(`${BASE_URL}/groups/\\d+`)); // \d+ matches one or more digits for ID
|
|
|
|
// Verify that the group name is displayed on the detail page
|
|
// Updated group name display selector on GroupDetailPage.vue
|
|
const groupNameDisplay = page.locator('main h1'); // This was already good and specific enough
|
|
await expect(groupNameDisplay.first()).toContainText(currentGroupName);
|
|
|
|
// (Optional) Verify other elements like member list or chore list if applicable
|
|
// await expect(page.locator('.member-list')).toBeVisible();
|
|
});
|
|
|
|
// The existing console.warn messages are appropriate.
|
|
test.skip('3. Update Group Name', async ({ page: _page }) => { // Intentionally skipped
|
|
// Reason: UI elements for editing group name/description (e.g., an "Edit Group" button
|
|
// or inline editing) are not currently present in GroupDetailPage.vue.
|
|
// This test should be enabled once the edit UI is implemented.
|
|
|
|
console.warn('Test "3. Update Group Name" is intentionally skipped: Edit functionality not yet available in UI.');
|
|
|
|
// Expected implementation would include:
|
|
// 1. Click an "Edit Group" button or enter edit mode
|
|
// 2. Modify the group name and/or description
|
|
// 3. Save changes
|
|
// 4. Verify the changes persist
|
|
});
|
|
|
|
test.skip('4. Delete a Group', async ({ page: _page }) => { // Intentionally skipped
|
|
// Reason: UI element for deleting an entire group (e.g., a "Delete Group" button)
|
|
// is not present on the GroupDetailPage.vue based on prior file inspection.
|
|
// If this feature is added, this test should be implemented.
|
|
console.warn('Skipping test "4. Delete a Group": UI for deleting group not found on GroupDetailPage.vue.');
|
|
// Placeholder for future implementation:
|
|
// await page.goto(`${BASE_URL}/groups`);
|
|
// await page.locator(`.neo-group-card:has-text("${currentGroupName}")`).click();
|
|
// await page.waitForURL(new RegExp(`${BASE_URL}/groups/\\d+`));
|
|
// page.on('dialog', dialog => dialog.accept()); // Handle confirmation dialog
|
|
// await page.locator('button:has-text("Delete Group")').click(); // Assuming a delete button
|
|
// await page.waitForURL(`${BASE_URL}/groups`);
|
|
// await expect(page.locator(`.neo-group-card:has-text("${currentGroupName}")`)).not.toBeVisible();
|
|
});
|