import { test, expect } from '@playwright/test'; test('DataTable comprehensive tests and scrolling benchmarks', async ({ page }) => { test.setTimeout(180000); page.on('console', msg => console.log('BROWSER LOG:', msg.text())); await page.goto('/test/index.html'); await page.waitForFunction(() => window.testStatus === 'passed', { timeout: 60000 }); console.log('DataTable initialized.'); // 1. 遍历验证第一行每个单元格的编辑与数据同步 await page.waitForSelector('.dt-row'); const fields = await page.evaluate(() => document.querySelector('DataTable').state.fields.map(f => ({ id: f.id, type: f.type }))); console.log('Fields to test:', fields.map(f => f.id).join(', ')); for (let i = 0; i < fields.length; i++) { const field = fields[i]; const colIdx = i + 1; console.log(`Testing Column [${field.id}] (Type: ${field.type})...`); if (field.id === 'actions' || field.id === 'id') { continue; } // 双击进入编辑 await page.evaluate((idx) => { const rows = document.querySelectorAll('.dt-row'); const row = rows[0]; const cells = row.querySelectorAll('.dt-cell'); const cell = cells[idx - 1]; cell.dispatchEvent(new MouseEvent('dblclick', { bubbles: true })); }, colIdx); const editorSelector = '.dt-editor-container'; await page.waitForSelector(editorSelector, { timeout: 5000 }); // 模拟输入 let newValue; if (field.type === 'switch' || field.id === 'active') { const oldVal = await page.evaluate(() => document.querySelector('DataTable').state.list[0].active); await page.click(`${editorSelector} .form-check-input`); newValue = !oldVal; } else if (field.type === 'select') { newValue = 'Editor'; await page.selectOption(`${editorSelector} select`, newValue); } else if (field.type === 'radio') { newValue = 'Female'; await page.click(`${editorSelector} input[value="Female"]`); } else if (field.type === 'textarea') { newValue = 'New multi-line content'; await page.fill(`${editorSelector} textarea`, newValue); } else if (field.type === 'TagsInput') { newValue = ['Playwright']; await page.fill(`${editorSelector} input`, 'Playwright'); await page.keyboard.press('Enter'); } else if (field.type === 'number') { newValue = 99; await page.fill(`${editorSelector} input`, '99'); } else if (field.type === 'date') { newValue = '2026-05-20'; await page.fill(`${editorSelector} input`, newValue); } else { newValue = `Edited ${field.id}`; await page.fill(`${editorSelector} input`, newValue); } // 退出编辑模式 await page.evaluate(() => { const table = document.querySelector('DataTable'); const row = table.state.list[0]; row._editingF = null; }); await page.waitForSelector(editorSelector, { state: 'detached', timeout: 5000 }); // 验证数据层 (State.js Proxy) 是否更新 const actualStateVal = await page.evaluate((id) => document.querySelector('DataTable').state.list[0][id], field.id); console.log(`Column [${field.id}] State value:`, actualStateVal); if (field.id === 'tags') { expect(actualStateVal).toContain('Playwright'); } else if (field.type === 'number') { expect(Number(actualStateVal)).toBe(99); } else { expect(String(actualStateVal)).toBe(String(newValue)); } // 验证视图层 (DOM) 是否同步渲染 const cellText = await page.evaluate((idx) => { const rows = document.querySelectorAll('.dt-row'); const row = rows[0]; const cells = row.querySelectorAll('.dt-cell'); return cells[idx - 1].textContent.trim(); }, colIdx); console.log(`Column [${field.id}] UI text:`, cellText); if (field.type !== 'switch' && field.id !== 'active') { expect(cellText).toContain(String(newValue).split('\n')[0]); } } console.log('All columns editing and persistence verified.'); // 2. 滚动测试 const scrollInfo = await page.evaluate(async () => { const el = document.querySelector('.dt-body'); el.scrollTop = 2000; await new Promise(r => setTimeout(r, 500)); return { scrollTop: el.scrollTop, renderedCount: el.querySelectorAll('.dt-row').length }; }); expect(scrollInfo.renderedCount).toBeGreaterThan(0); });