import { test, expect } from '@playwright/test'; test('create → mine → review/sign → owned inscription → block/transaction → reload/load', async ({page}) => { const errors=[], remote=[]; page.on('pageerror',e=>errors.push(e.message)); page.on('request',r=>{ if(!r.url().startsWith('http://127.0.0.1:4178')) remote.push(r.url()); }); await page.goto('/'); await expect(page.getByRole('button',{name:'Mine a block'})).toBeDisabled(); await page.getByRole('button',{name:'Create test wallet'}).click(); await expect(page.locator('#address')).toHaveValue(/^bcrt1p/); await page.getByRole('button',{name:'Mine a block'}).click(); await expect(page.locator('#balance')).toHaveText('50.00000000'); const payload=' Hello 🌱'; await page.getByLabel('What will you put on your chain?').fill(payload); await page.getByRole('button',{name:'Review inscription'}).click(); await expect(page.locator('#review-text')).toHaveText(payload); await expect(page.locator('#pending')).toHaveText('0'); await page.getByRole('button',{name:'Sign & inscribe'}).click(); await expect(page.locator('#pending')).toHaveText('2'); await expect(page.locator('.collectible pre')).toHaveText(payload); await expect(page.locator('.collectible .tag')).toContainText('PENDING'); await expect(page.locator('#balance')).toHaveText('49.99999000'); await page.reload(); await expect(page.locator('.collectible pre')).toHaveText(payload); await expect(page.locator('#pending')).toHaveText('2'); await page.getByRole('button',{name:'Mine a block'}).click(); await expect(page.locator('.collectible .tag')).toHaveText('CONFIRMED · BLOCK 2'); await page.getByRole('link',{name:'View reveal transaction'}).click(); await expect(page.locator('#inspector')).toContainText('1 confirmation(s)'); await expect(page.locator('#inspector')).toContainText('Raw Bitcoin transaction'); await page.getByRole('link',{name:'Inspect commit transaction'}).click(); await expect(page.locator('#inspector')).toContainText('4,999,998,000 sats'); await page.getByRole('link',{name:'View block 2'}).click(); await expect(page.locator('#inspector h2')).toHaveText('Block 2'); await expect(page.locator('#inspector a')).toHaveCount(3); await page.getByRole('link',{name:/^Inscription /}).click(); await expect(page.locator('#inspector')).toContainText('Inscription detail'); const [download] = await Promise.all([page.waitForEvent('download'),page.getByRole('button',{name:'Save complete lab'}).click()]); const backupPath=await download.path(); page.on('dialog',dialog=>dialog.accept()); await page.getByRole('button',{name:'Reset local lab'}).click(); await expect(page.getByRole('button',{name:'Create test wallet'})).toBeVisible(); await page.locator('#load-wallet').setInputFiles(backupPath); await expect(page.locator('.collectible pre')).toHaveText(payload); await expect(page.locator('#height')).toHaveText('2'); await page.reload(); await expect(page.locator('#balance')).toHaveText('99.99999000'); expect(await page.evaluate(()=>window.unwanted)).toBeUndefined(); expect(errors).toEqual([]); expect(remote).toEqual([]); expect(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth)).toBeTruthy(); await page.screenshot({path:`test-results/${test.info().project.name}-complete.png`,fullPage:true}); }); test('wallet backup reload and rejected oversized or invalid input',async({page})=>{ await page.goto('/'); await page.getByRole('button',{name:'Create test wallet'}).click(); await expect(page.locator('#address')).toHaveValue(/^bcrt1p/); const address=await page.locator('#address').inputValue(); const [download]=await Promise.all([page.waitForEvent('download'),page.getByRole('button',{name:'Save test wallet'}).click()]); await page.getByRole('button',{name:'Mine a block'}).click(); await page.locator('#payload').fill('🌱'.repeat(71)); await page.getByRole('button',{name:'Review inscription'}).click(); await expect(page.getByRole('status')).toContainText('at most 280'); await expect(page.locator('#pending')).toHaveText('0'); await page.locator('#load-wallet').setInputFiles({name:'bad.json',mimeType:'application/json',buffer:Buffer.from('{"network":"mainnet"}')}); await expect(page.getByRole('status')).toContainText('Only Super Testnet'); await expect(page.locator('#address')).toHaveValue(address); page.on('dialog',d=>d.accept()); await page.locator('#load-wallet').setInputFiles(await download.path()); await expect(page.getByRole('status')).toContainText('Test wallet loaded.'); await expect(page.locator('#address')).toHaveValue(address); await expect(page.locator('#balance')).toHaveText('50.00000000'); }); test('two tabs serialize mining and refresh shared storage',async({page,context})=>{ await page.goto('/'); await page.getByRole('button',{name:'Create test wallet'}).click(); await expect(page.locator('#address')).toHaveValue(/^bcrt1p/); const other=await context.newPage(); await other.goto('/'); await Promise.all([page.getByRole('button',{name:'Mine a block'}).click(),other.getByRole('button',{name:'Mine a block'}).click()]); await expect(page.locator('#height')).toHaveText('2'); await expect(other.locator('#height')).toHaveText('2'); await expect(page.locator('#balance')).toHaveText('100.00000000'); }); test('storage failure leaves the displayed and persisted chain unchanged', async ({page}) => { await page.goto('/'); await page.getByRole('button',{name:'Create test wallet'}).click(); await expect(page.locator('#address')).toHaveValue(/^bcrt1p/); await page.evaluate(()=>{ Storage.prototype.setItem = () => { throw new DOMException('Quota exceeded','QuotaExceededError'); }; }); await page.getByRole('button',{name:'Mine a block'}).click(); await expect(page.getByRole('status')).toContainText('No changes were saved'); await expect(page.locator('#height')).toHaveText('0'); await expect(page.locator('#balance')).toHaveText('0.00000000'); await page.reload(); await expect(page.locator('#height')).toHaveText('0'); await page.getByRole('button',{name:'Mine a block'}).click(); await expect(page.locator('#balance')).toHaveText('50.00000000'); });