import { chromium } from 'playwright'; import { mkdirSync } from 'fs'; const screenshotDir = 'C:/tmp/playwright_screenshots'; mkdirSync(screenshotDir, { recursive: true }); const browser = await chromium.launch({ headless: true }); const context = await browser.newContext({ viewport: { width: 1400, height: 900 } }); const page = await context.newPage(); async function screenshot(name) { const path = `${screenshotDir}/${name}.png`; await page.screenshot({ path, fullPage: false }); console.log(` [Screenshot: ${name}.png]`); } // Login await page.goto('http://localhost:3000/fertilizer/new'); await page.waitForLoadState('networkidle'); if (page.url().includes('/login')) { await page.fill('#username', 'akira'); await page.fill('input[type="password"]', 'keina2025'); await page.click('button[type="submit"]'); await page.waitForNavigation({ timeout: 10000 }).catch(() => {}); await page.waitForLoadState('networkidle'); await page.goto('http://localhost:3000/fertilizer/new'); await page.waitForLoadState('networkidle'); } // Select にこまる const selects = await page.locator('select').all(); await selects[1].selectOption({ label: 'にこまる' }); await page.waitForTimeout(1000); // Click + 肥料を追加 const addBtn = page.locator('button').filter({ hasText: '肥料を追加' }).first(); await addBtn.click(); await page.waitForTimeout(500); // Click グアノ in modal await page.locator('text=グアノ').first().click(); await page.waitForTimeout(1000); // Step 5: Enter "3" in the param field and click 計算 console.log('\n=== Step 5: Enter "3" in param field and click 計算 ==='); // The first input with placeholder "値" is the param field const paramInput = page.locator('input[placeholder="値"]'); const paramVisible = await paramInput.isVisible(); console.log('Param input visible:', paramVisible); await paramInput.fill('3'); await page.waitForTimeout(300); const calcBtn = page.locator('button').filter({ hasText: '計算' }); await calcBtn.click(); await page.waitForTimeout(1500); await screenshot('step5_after_calc'); // Step 6: Check matrix cells - do they show decimal values in input fields? console.log('\n=== Step 6: Check matrix cell values BEFORE clicking ≈ ==='); const allInputs = await page.locator('input[type="number"]').all(); console.log('Number of number inputs:', allInputs.length); for (let i = 0; i < Math.min(allInputs.length, 20); i++) { const val = await allInputs[i].inputValue(); const placeholder = await allInputs[i].getAttribute('placeholder'); console.log(` Input[${i}]: value="${val}", placeholder="${placeholder}"`); } // Step 7: Find and examine the グアノ column header button (≈ button) console.log('\n=== Step 7: Find ≈ button in グアノ column header ==='); // Look for buttons with ≈ or similar content const allButtons = await page.locator('button').all(); console.log('Total buttons on page:', allButtons.length); for (let i = 0; i < allButtons.length; i++) { const text = await allButtons[i].textContent(); const cls = await allButtons[i].getAttribute('class'); if (text && (text.includes('≈') || text.includes('↩') || text.includes('~') || text.trim().length <= 3)) { console.log(` Button[${i}]: text="${text?.trim()}", class="${cls?.substring(0, 100)}"`); } } // Get page text in the グアノ column area const bodyText = await page.locator('body').textContent(); const guanoSection = bodyText?.match(/グアノ.{0,300}/)?.[0]; console.log('グアノ section text:', guanoSection); await browser.close();