mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 02:51:12 -05:00
140 lines
4.8 KiB
TypeScript
140 lines
4.8 KiB
TypeScript
/**
|
|
* Moderation Approval Flow E2E Tests
|
|
*
|
|
* Tests the complete submission approval process.
|
|
*/
|
|
|
|
import { test, expect } from '@playwright/test';
|
|
import { ModerationQueuePage } from '../../helpers/page-objects/ModerationQueuePage';
|
|
import { ParkCreationPage } from '../../helpers/page-objects/ParkCreationPage';
|
|
import { generateParkData, generateTestId } from '../../fixtures/test-data';
|
|
import { queryDatabase, cleanupTestData, waitForVersion } from '../../fixtures/database';
|
|
|
|
test.describe('Submission Approval Flow', () => {
|
|
test.afterAll(async () => {
|
|
await cleanupTestData();
|
|
});
|
|
|
|
test('should approve park submission and create entity', async ({ browser }) => {
|
|
// Step 1: Create submission as regular user
|
|
const userContext = await browser.newContext({ storageState: '.auth/user.json' });
|
|
const userPage = await userContext.newPage();
|
|
|
|
const parkData = generateParkData({
|
|
name: `Test Park ${generateTestId()}`,
|
|
});
|
|
|
|
const parkCreationPage = new ParkCreationPage(userPage);
|
|
await parkCreationPage.goto();
|
|
await parkCreationPage.fillBasicInfo(parkData.name, parkData.description);
|
|
await parkCreationPage.submitForm();
|
|
await parkCreationPage.expectSuccess();
|
|
|
|
await userContext.close();
|
|
|
|
// Step 2: Approve as moderator
|
|
const modContext = await browser.newContext({ storageState: '.auth/moderator.json' });
|
|
const modPage = await modContext.newPage();
|
|
|
|
const moderationPage = new ModerationQueuePage(modPage);
|
|
await moderationPage.goto();
|
|
|
|
// Find the submission
|
|
await moderationPage.expectSubmissionVisible(parkData.name);
|
|
|
|
// Claim it
|
|
await moderationPage.claimSubmission(0);
|
|
|
|
// Approve it
|
|
await moderationPage.approveSubmission('Looks good!');
|
|
|
|
// Step 3: Verify entity created in database
|
|
await modPage.waitForTimeout(2000); // Give DB time to process
|
|
|
|
const parks = await queryDatabase('parks', (qb) =>
|
|
qb.select('*').eq('name', parkData.name)
|
|
);
|
|
|
|
expect(parks).toHaveLength(1);
|
|
expect(parks[0].is_test_data).toBe(true);
|
|
|
|
// Step 4: Verify version created
|
|
const versions = await queryDatabase('park_versions', (qb) =>
|
|
qb.select('*').eq('park_id', parks[0].id).eq('version_number', 1)
|
|
);
|
|
|
|
expect(versions).toHaveLength(1);
|
|
expect(versions[0].change_type).toBe('created');
|
|
|
|
// Step 5: Verify submission marked as approved
|
|
const submissions = await queryDatabase('content_submissions', (qb) =>
|
|
qb.select('*').eq('entity_type', 'park').contains('submission_data', { name: parkData.name })
|
|
);
|
|
|
|
expect(submissions[0].status).toBe('approved');
|
|
expect(submissions[0].approved_by).toBeTruthy();
|
|
expect(submissions[0].approved_at).toBeTruthy();
|
|
|
|
// Step 6: Verify lock released
|
|
expect(submissions[0].assigned_to).toBeNull();
|
|
expect(submissions[0].locked_until).toBeNull();
|
|
|
|
await modContext.close();
|
|
});
|
|
|
|
test('should show change comparison for edits', async ({ browser }) => {
|
|
// This test would require:
|
|
// 1. Creating and approving a park
|
|
// 2. Editing the park
|
|
// 3. Viewing the edit in moderation queue
|
|
// 4. Verifying change comparison displays
|
|
// Left as TODO - requires more complex setup
|
|
});
|
|
|
|
test('should send notification to submitter on approval', async ({ browser }) => {
|
|
// This test would verify that Novu notification is sent
|
|
// Left as TODO - requires Novu testing setup
|
|
});
|
|
|
|
test('should prevent approval without lock', async ({ browser }) => {
|
|
// Create submission as user
|
|
const userContext = await browser.newContext({ storageState: '.auth/user.json' });
|
|
const userPage = await userContext.newPage();
|
|
|
|
const parkData = generateParkData({
|
|
name: `Test Park ${generateTestId()}`,
|
|
});
|
|
|
|
const parkCreationPage = new ParkCreationPage(userPage);
|
|
await parkCreationPage.goto();
|
|
await parkCreationPage.fillBasicInfo(parkData.name, parkData.description);
|
|
await parkCreationPage.submitForm();
|
|
await parkCreationPage.expectSuccess();
|
|
|
|
await userContext.close();
|
|
|
|
// Try to approve as moderator WITHOUT claiming
|
|
const modContext = await browser.newContext({ storageState: '.auth/moderator.json' });
|
|
const modPage = await modContext.newPage();
|
|
|
|
const moderationPage = new ModerationQueuePage(modPage);
|
|
await moderationPage.goto();
|
|
|
|
// Approve button should be disabled or not visible
|
|
const approveButton = modPage.locator('button:has-text("Approve")').first();
|
|
await expect(approveButton).toBeDisabled();
|
|
|
|
await modContext.close();
|
|
});
|
|
});
|
|
|
|
test.describe('Bulk Approval', () => {
|
|
test('should approve all items in submission', async ({ browser }) => {
|
|
// TODO: Test approving all submission items at once
|
|
});
|
|
|
|
test('should allow selective item approval', async ({ browser }) => {
|
|
// TODO: Test approving only specific items from a submission
|
|
});
|
|
});
|