Add CBOR metadata indexes, local API and coordinated auto mining

This commit is contained in:
Codex committed 2026-10-05 02:33:54 +00:00
1 parent 0405452ab2
commit aa39db3879
14 files changed
+599 -54

No files matched your search

+88 -7
View File
@@ -5,11 +5,11 @@ test('create → mine → mempool → inscription → block/transaction → relo
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 expect(page.getByRole('button',{name:'Mine now'})).toBeDisabled();
await expect(page.locator('#mempool-list')).toContainText('Mempool empty');
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 page.getByRole('button',{name:'Mine now'}).click();
await expect(page.locator('#balance')).toHaveText('50.00000000');
await expect(page.locator('#blocks .block-card')).toHaveCount(1);
await expect(page.locator('#blocks .block-card').first()).toContainText('HEIGHT 1');
@@ -32,7 +32,7 @@ test('create → mine → mempool → inscription → block/transaction → relo
await expect(page.locator('.collectible pre')).toHaveText(payload);
await expect(page.locator('#pending')).toHaveText('2');
await expect(page.locator('#mempool-list .mempool-card')).toHaveCount(2);
await page.getByRole('button',{name:'Mine a block'}).click();
await page.getByRole('button',{name:'Mine now'}).click();
await expect(page.locator('#mempool-list')).toContainText('Mempool empty');
await expect(page.locator('#blocks .block-card')).toHaveCount(2);
await expect(page.locator('#blocks .block-card').first()).toContainText('HEIGHT 2');
@@ -90,7 +90,7 @@ test('wallet backup reload and rejected oversized or invalid input',async({page}
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.getByRole('button',{name:'Mine now'}).click();
await page.locator('#payload').fill('🌱'.repeat(4097));
await page.getByRole('button',{name:'Review inscription'}).click();
await expect(page.getByRole('status')).toContainText('at most 16384');
@@ -109,7 +109,7 @@ 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 Promise.all([page.getByRole('button',{name:'Mine now'}).click(),other.getByRole('button',{name:'Mine now'}).click()]);
await expect(page.locator('#height')).toHaveText('2');
await expect(other.locator('#height')).toHaveText('2');
await expect(page.locator('#balance')).toHaveText('100.00000000');
@@ -120,13 +120,13 @@ test('storage failure leaves the displayed and persisted chain unchanged', async
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 page.getByRole('button',{name:'Mine now'}).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 page.getByRole('button',{name:'Mine now'}).click();
await expect(page.locator('#balance')).toHaveText('50.00000000');
});
test('MIME upload, reset only after success, and parent/child navigation', async ({ page }) => {
@@ -175,3 +175,84 @@ test('HTML preview cannot execute, navigate or fetch remote resources', async ({
expect(remote).toEqual([]);
await expect(page).toHaveURL('http://127.0.0.1:4178/');
});
test('metadata review validation, witness persistence, indexes/reducer and local API explorer', async ({page,context}) => {
await page.goto('/'); await page.locator('#create-wallet').click(); await page.locator('#mine').click();
await page.locator('#payload').fill('independent body');
await page.locator('#metadata').fill('{bad'); await page.locator('#review').click();
await expect(page.getByRole('status')).toContainText('Invalid metadata JSON');
await expect(page.locator('#review-panel')).toBeHidden();
await page.locator('#metadata').fill(JSON.stringify({large:'x'.repeat(2048)})); await page.locator('#review').click();
await expect(page.getByRole('status')).toContainText('2048 CBOR');
await expect(page.locator('#pending')).toHaveText('0');
const metadata={protocol:'example',note:'chunked '+ 'x'.repeat(600),nested:{data:true},code:'window.unwanted=true'};
await page.locator('#metadata').fill(JSON.stringify(metadata));
await page.locator('#review').click();
await expect(page.locator('#review-metadata')).toContainText('CBOR, tag 5');
await page.locator('#sign').click();
await expect(page.locator('#metadata')).toHaveValue('');
await expect(page.locator('#metadata-count')).toContainText('0 / 2048');
await expect(page.locator('.metadata-document')).toContainText('example');
await page.reload();
await expect(page.locator('.metadata-document')).toContainText('chunked');
await page.getByRole('link',{name:/^Inscription /}).click();
await expect(page.locator('#inspector .metadata-document')).toContainText('example');
await expect(page.locator('#index-stats')).toContainText('1 events · 1 with metadata · 0 confirmed · 1 pending · 1 protocols');
await page.locator('#protocol').selectOption('"example"');
await expect(page.locator('#protocol-events')).not.toContainText('independent'); // Body is not part of metadata events.
await page.locator('#reducer').selectOption('event-counter');
await expect(page.locator('#derived-state')).toContainText('"count": 1');
await expect(page.locator('#protocol-events')).toContainText('"status": "pending"');
await page.locator('#mine').click();
await expect(page.locator('#protocol-events')).toContainText('"status": "confirmed"');
await expect(page.locator('#derived-state')).toContainText('"confirmed": 1');
await expect(page.locator('#api-explorer')).toContainText('LOCAL / IN-BROWSER');
await page.locator('#api-preset').selectOption('/r/inscription/:id'); await page.locator('#api-try').click();
await expect(page.locator('#api-response')).toContainText('"protocol": "example"');
await page.locator('#api-preset').selectOption('/content/:id'); await page.locator('#api-try').click();
await expect(page.locator('#api-response')).toContainText('independent body');
await page.locator('#api-path').fill('/r/blockheight'); await page.locator('#api-try').click();
await expect(page.locator('#api-response')).toContainText('"body": 2');
await context.grantPermissions(['clipboard-read','clipboard-write']);
await page.locator('#api-copy').click();
expect(await page.evaluate(()=>navigator.clipboard.readText())).toContain('"body": 2');
await page.locator('#api-path').fill('/missing'); await page.locator('#api-try').click();
await expect(page.locator('#api-response')).toContainText('404');
expect(await page.evaluate(()=>window.unwanted)).toBeUndefined();
expect(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth)).toBeTruthy();
});
test('auto miner default, preference reload, countdown, pending confirmation, manual reset and OFF', async ({page}) => {
await page.clock.install();
await page.goto('/'); await page.locator('#create-wallet').click();
await expect(page.locator('#miner-interval')).toHaveValue('0');
await expect(page.locator('#miner-status')).toHaveText('Auto mining OFF');
await page.locator('#miner-interval').selectOption('10');
await expect(page.locator('#miner-status')).toContainText('10s interval');
await page.clock.runFor(10000);
await expect(page.locator('#height')).toHaveText('1');
await page.locator('#payload').fill('auto confirmed'); await page.locator('#review').click(); await page.locator('#sign').click();
await expect(page.locator('#pending')).toHaveText('2');
await page.clock.runFor(10000);
await expect(page.locator('#height')).toHaveText('2'); await expect(page.locator('#pending')).toHaveText('0');
await page.locator('#miner-interval').selectOption('30');
await page.reload(); await expect(page.locator('#miner-interval')).toHaveValue('30');
await page.locator('#miner-interval').selectOption('60');
await page.clock.runFor(5000); await expect(page.locator('#miner-status')).toContainText('55s');
await page.locator('#mine').click(); await expect(page.locator('#height')).toHaveText('3');
await expect(page.locator('#miner-status')).toContainText('60s');
await page.locator('#miner-interval').selectOption('0');
await page.clock.runFor(65000); await expect(page.locator('#height')).toHaveText('3');
});
test('two tabs race one auto deadline under Web Locks', async ({page,context}) => {
const now = new Date('2026-10-05T12:00:00Z');
await page.clock.install({time:now}); await page.goto('/'); await page.locator('#create-wallet').click();
const other=await context.newPage(); await other.clock.install({time:now}); await other.goto('/');
await page.locator('#miner-interval').selectOption('10');
await expect(other.locator('#miner-interval')).toHaveValue('10');
await Promise.all([page.clock.runFor(10000),other.clock.runFor(10000)]);
await expect(page.locator('#height')).toHaveText('1'); await expect(other.locator('#height')).toHaveText('1');
await page.locator('#miner-interval').selectOption('0');
await expect(other.locator('#miner-interval')).toHaveValue('0');
});