import { test, expect } from '@playwright/test' import { testFormData, ConflictResolutionFormHelper, MarkdownValidator } from './conflict-resolution-utils' test.describe('Conflict Resolution Framework - Form to Markdown Parity', () => { test('Complete form fill and validate 100% parity with markdown output', async ({ page }) => { const formHelper = new ConflictResolutionFormHelper(page) // Navigate to the form await formHelper.goto() await expect(page.locator('h1:has-text("CONFLICT RESOLUTION FRAMEWORK")').first()).toBeVisible() // Fill all form sections systematically await test.step('Fill basic organization information', async () => { await formHelper.fillBasicInfo(testFormData) }) await test.step('Fill core values section', async () => { await formHelper.fillCoreValues(testFormData) }) await test.step('Fill conflict types section', async () => { await formHelper.fillConflictTypes(testFormData) }) await test.step('Fill resolution approach section', async () => { await formHelper.fillApproach(testFormData) }) await test.step('Fill report receivers section', async () => { await formHelper.fillReportReceivers(testFormData) }) await test.step('Fill mediator structure section', async () => { await formHelper.fillMediatorStructure(testFormData) }) await test.step('Fill process steps section', async () => { await formHelper.fillProcessSteps(testFormData) }) await test.step('Fill timeline section', async () => { await formHelper.fillTimeline(testFormData) }) await test.step('Fill available actions section', async () => { await formHelper.fillAvailableActions(testFormData) }) await test.step('Fill documentation section', async () => { await formHelper.fillDocumentation(testFormData) }) await test.step('Fill implementation section', async () => { await formHelper.fillImplementation(testFormData) }) await test.step('Fill enhanced sections', async () => { await formHelper.fillEnhancedSections(testFormData) }) // Wait for auto-save to complete await page.waitForTimeout(1000) // Validate form completion await test.step('Validate form completion', async () => { await page.locator('button:has-text("CHECK")').click() // Should see success message await expect(page.locator('text=Form is complete')).toBeVisible({ timeout: 5000 }) }) // Generate and download markdown const markdownContent = await test.step('Download markdown', async () => { return await formHelper.downloadMarkdown() }) // Validate markdown content against form data await test.step('Validate markdown parity', async () => { const validator = new MarkdownValidator(markdownContent) const errors = validator.validateAll(testFormData) if (errors.length > 0) { console.log('Markdown content:', markdownContent.substring(0, 1000) + '...') console.log('Validation errors:', errors) } expect(errors).toEqual([]) }) // Additional specific validations await test.step('Validate document structure', async () => { expect(markdownContent).toContain('# Test Cooperative Solutions Conflict Resolution Policy') expect(markdownContent).toContain('## Purpose') expect(markdownContent).toContain('## Who does this policy apply to?') expect(markdownContent).toContain('## What policy should be used?') expect(markdownContent).toContain('## Guiding principles') expect(markdownContent).toContain('## Definitions') expect(markdownContent).toContain('## Responsibility for implementation') expect(markdownContent).toContain('## Procedures') expect(markdownContent).toContain('### Reflection') expect(markdownContent).toContain('## Direct Resolution') expect(markdownContent).toContain('## Assisted Resolution') expect(markdownContent).toContain('### Formal Complaints') expect(markdownContent).toContain('## Other Redress') expect(markdownContent).toContain('## Acknowledgments') }) await test.step('Validate data integrity', async () => { // Check that no placeholder text remains expect(markdownContent).not.toContain('[Organization Name]') expect(markdownContent).not.toContain('[Date]') expect(markdownContent).not.toContain('[Not specified]') expect(markdownContent).not.toContain('[None selected]') // Check proper possessive forms expect(markdownContent).toContain("Test Cooperative Solutions'") expect(markdownContent).not.toContain("Test Cooperative Solutions's") // Check no redundant text expect(markdownContent).not.toContain('within within') expect(markdownContent).not.toContain('members members') }) }) test('Validate organization type variations', async ({ page }) => { const formHelper = new ConflictResolutionFormHelper(page) for (const orgType of ['Worker Cooperative', 'Consumer Cooperative', 'Nonprofit Organization', 'Social Enterprise']) { await test.step(`Test organization type: ${orgType}`, async () => { await formHelper.goto() // Fill minimal data with specific org type await page.fill('input[placeholder*="organization name"]', `Test ${orgType}`) const orgTypeButton = page.locator('button:has-text("Select organization type"), [role="combobox"]:has-text("Select organization type")').first() await orgTypeButton.click() await page.locator(`text="${orgType}"`).click() await page.fill('input[type="number"]', '5') // Select one conflict type to make form valid await page.locator('label:has-text("Financial disagreements") input[type="checkbox"]').check() // Check validation await page.locator('button:has-text("CHECK")').click() await expect(page.locator('text=Form is complete')).toBeVisible({ timeout: 5000 }) // Download and validate const markdown = await formHelper.downloadMarkdown() // Validate org type specific content if (orgType.includes('Cooperative')) { expect(markdown).toContain('members') expect(markdown).toContain('Directors, staff, members') } else { expect(markdown).toContain('community members') expect(markdown).toContain('Directors, staff, community members') } // Check possessive handling expect(markdown).toContain(`Test ${orgType}`) expect(markdown).not.toContain(`Test ${orgType}'s's`) }) } }) test('Validate checkbox selections integrity', async ({ page }) => { const formHelper = new ConflictResolutionFormHelper(page) await formHelper.goto() // Fill basic info await page.fill('input[placeholder*="organization name"]', 'Checkbox Test Org') const orgTypeButton = page.locator('button:has-text("Select organization type"), [role="combobox"]:has-text("Select organization type")').first() await orgTypeButton.click() await page.locator('text="Worker Cooperative"').click() await page.fill('input[type="number"]', '8') // Test specific checkbox combinations const checkboxTests = [ { section: 'Core Values', items: ['Mutual Care', 'Anti-Oppression', 'Collective Liberation'], shouldFind: ['Mutual Care', 'Anti-Oppression', 'Collective Liberation'] }, { section: 'Conflict Types', items: ['Code of Conduct violations', 'Harassment or discrimination', 'Conflicts of interest'], shouldFind: ['Code of Conduct violations', 'Harassment or discrimination', 'Conflicts of interest'] }, { section: 'Available Actions', items: ['Verbal warning', 'Mediation facilitation', 'Removal from organization'], shouldFind: ['Verbal warning', 'Mediation facilitation', 'Removal from organization'] } ] for (const test of checkboxTests) { await test.step(`Test ${test.section} checkboxes`, async () => { // Clear any existing selections first for (const item of test.items) { const checkbox = page.locator(`label:has-text("${item}") input[type="checkbox"]`) if (await checkbox.isChecked()) { await checkbox.uncheck() } } // Select specific items for (const item of test.items) { await page.locator(`label:has-text("${item}") input[type="checkbox"]`).check() } // Download markdown const markdown = await formHelper.downloadMarkdown() // Validate each selected item appears for (const expectedItem of test.shouldFind) { expect(markdown).toContain(expectedItem) } }) } }) test('Validate toggle sections functionality', async ({ page }) => { const formHelper = new ConflictResolutionFormHelper(page) await formHelper.goto() // Fill basic required fields await page.fill('input[placeholder*="organization name"]', 'Toggle Test Org') const orgTypeButton = page.locator('button:has-text("Select organization type"), [role="combobox"]:has-text("Select organization type")').first() await orgTypeButton.click() await page.locator('text="Nonprofit Organization"').click() await page.fill('input[type="number"]', '6') await page.locator('label:has-text("Financial disagreements") input[type="checkbox"]').check() // Test toggleable sections const toggleSections = [ { name: 'Reflection', content: 'reflection process' }, { name: 'Direct Resolution', content: 'escalate the bandwidth' }, { name: 'External Resources', content: 'Human Rights Commission' } ] for (const section of toggleSections) { await test.step(`Test ${section.name} section toggle`, async () => { // Find and enable toggle const toggle = page.locator(`.toggle:near(:text("${section.name}"))`).first() if (await toggle.isVisible()) { await toggle.click() await page.waitForTimeout(500) // Wait for UI update } // Download markdown const markdown = await formHelper.downloadMarkdown() // Section should be included when toggled on expect(markdown.toLowerCase()).toContain(section.content.toLowerCase()) // Toggle off and test again if (await toggle.isVisible()) { await toggle.click() await page.waitForTimeout(500) } const markdownOff = await formHelper.downloadMarkdown() // For some sections, content might still appear in different contexts // So we check for section-specific markers if (section.name === 'Reflection') { expect(markdownOff).not.toContain('### Reflection') } }) } }) test('Validate form validation prevents incomplete exports', async ({ page }) => { const formHelper = new ConflictResolutionFormHelper(page) await formHelper.goto() // Test with minimal/incomplete data await page.fill('input[placeholder*="organization name"]', 'Incomplete Org') // Deliberately don't fill other required fields // Try validation await page.locator('button:has-text("CHECK")').click() // Should see error message await expect(page.locator(':has-text("complete")', { timeout: 5000 })).toBeVisible() await expect(page.locator(':has-text("required")')).toBeVisible() // Now complete required fields const orgTypeButton = page.locator('button:has-text("Select organization type"), [role="combobox"]:has-text("Select organization type")').first() await orgTypeButton.click() await page.locator('text="Social Enterprise"').click() await page.fill('input[type="number"]', '3') await page.locator('label:has-text("Financial disagreements") input[type="checkbox"]').check() // Try validation again await page.locator('button:has-text("CHECK")').click() await expect(page.locator('text=Form is complete')).toBeVisible({ timeout: 5000 }) }) test('Validate date handling and formatting', async ({ page }) => { const formHelper = new ConflictResolutionFormHelper(page) await formHelper.goto() // Fill basic info await page.fill('input[placeholder*="organization name"]', 'Date Test Org') const orgTypeButton = page.locator('button:has-text("Select organization type"), [role="combobox"]:has-text("Select organization type")').first() await orgTypeButton.click() await page.locator('text="Worker Cooperative"').click() await page.fill('input[type="number"]', '4') await page.locator('label:has-text("Financial disagreements") input[type="checkbox"]').check() // Fill specific dates const testDates = { created: '2024-01-15', review: '2025-01-15' } await page.fill('input[type="date"]:first-of-type', testDates.created) await page.fill('input[type="date"]:last-of-type', testDates.review) // Download and validate const markdown = await formHelper.downloadMarkdown() expect(markdown).toContain(testDates.created) expect(markdown).toContain(testDates.review) // Check proper date formatting in context expect(markdown).toContain(`*This policy was created on ${testDates.created}`) expect(markdown).toContain(`*Next review date: ${testDates.review}*`) }) })