Add CBOR metadata indexes, local API and coordinated auto mining
This commit is contained in:
1 parent
0405452ab2
commit
aa39db3879
14 files changed
+599
-54
No files matched your search
+88
-7
@@ -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');
|
||||
});
|
||||
Reference in new issue
Block a user