Some checks failed
Use-case regression gate / usecase-regressions (push) Has been cancelled
Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a10e2d-a5ef-7e92-b03d-b1694e915680
82 lines
4.3 KiB
JavaScript
82 lines
4.3 KiB
JavaScript
// Browser acceptance with synthetic content and intercepted clipboard writes.
|
|
import assert from 'node:assert/strict';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { chromium } from 'playwright';
|
|
|
|
const browser = await chromium.launch({headless: true});
|
|
try {
|
|
const page = await browser.newPage();
|
|
const script = fileURLToPath(new URL('../coulomb_social/apps/spaces/static/spaces/copy-content.js', import.meta.url));
|
|
const expected = "Synthetic protocol\n\n*Synthetic board call*\n\n## Weekly call\n\n- Open point\n - Nested follow-up\n- Completed point\n\n### Protocol\n\nNew notes with **emphasis**.\n\nxxx";
|
|
const exportedHtml = '<p>Synthetic protocol</p><p><em>Synthetic board call</em></p><h2>Weekly call</h2><ul><li>Open point<ul><li>Nested follow-up</li></ul></li><li>Completed point</li></ul><h3>Protocol</h3><p>New notes with <strong>emphasis</strong>.</p><p>xxx</p>';
|
|
const fixture = `<nav>PRIVATE APP CHROME</nav>
|
|
<button id="copy-page-content">Copy content to clipboard</button>
|
|
<p id="copy-content-status" role="status"></p>
|
|
<textarea id="copy-content-manual" hidden></textarea>
|
|
<script type="application/json" id="page-clipboard-text">${JSON.stringify(expected)}</script>
|
|
<script type="application/json" id="page-clipboard-html">${JSON.stringify(exportedHtml)}</script>
|
|
<div id="page-content"><h1>Weekly call</h1><ul><li>Open point<ul><li>Nested follow-up</li></ul></li><li>Completed point</li></ul><h2>Protocol</h2><p>New notes with <strong>emphasis</strong>.</p></div>`;
|
|
// A secure origin enables the browser's native ClipboardItem implementation.
|
|
await page.route('https://clipboard.test/', route => route.fulfill({
|
|
contentType: 'text/html', body: fixture,
|
|
}));
|
|
await page.goto('https://clipboard.test/');
|
|
async function setup(mode) {
|
|
await page.setContent(fixture);
|
|
await page.evaluate(mode => {
|
|
window.receipts = [];
|
|
window.clipboardMode = mode;
|
|
Object.defineProperty(navigator, 'clipboard', {configurable: true, value: {
|
|
write: async items => {
|
|
if (window.clipboardMode !== 'rich') throw new Error('Rich clipboard denied');
|
|
const item = items[0];
|
|
window.receipts.push({html: await (await item.getType('text/html')).text(),
|
|
text: await (await item.getType('text/plain')).text()});
|
|
},
|
|
writeText: async text => {
|
|
if (window.clipboardMode === 'denied') throw new Error('Clipboard denied');
|
|
window.receipts.push({text});
|
|
},
|
|
}});
|
|
}, mode);
|
|
await page.addScriptTag({path: script});
|
|
}
|
|
for (const mode of ['rich', 'plain', 'denied']) {
|
|
await setup(mode);
|
|
await page.locator('#copy-page-content').click();
|
|
await page.waitForFunction(() => !document.getElementById('copy-page-content').disabled);
|
|
const result = await page.evaluate(() => ({
|
|
receipts: window.receipts,
|
|
status: document.getElementById('copy-content-status').textContent,
|
|
manual: document.getElementById('copy-content-manual').value,
|
|
hidden: document.getElementById('copy-content-manual').hidden,
|
|
selected: document.getElementById('copy-content-manual').selectionEnd,
|
|
}));
|
|
const text = mode === 'denied' ? result.manual : result.receipts[0].text;
|
|
assert.equal(text, expected);
|
|
assert.match(text, /Weekly call/);
|
|
assert.match(text, /- Open point/);
|
|
assert.match(text, / - Nested follow-up/);
|
|
assert.match(text, /- Completed point/);
|
|
assert.match(text, /New notes with \*\*emphasis\*\*/);
|
|
assert.doesNotMatch(text, /PRIVATE APP CHROME|Copy content to clipboard/);
|
|
if (mode === 'denied') {
|
|
assert.equal(result.receipts.length, 0);
|
|
assert.equal(result.hidden, false);
|
|
assert.equal(result.selected, result.manual.length);
|
|
assert.match(result.status, /Ctrl\+C or Cmd\+C/);
|
|
assert.doesNotMatch(result.status, /Content copied/);
|
|
} else {
|
|
assert.equal(result.receipts.length, 1);
|
|
assert.match(result.status, /Content copied/);
|
|
if (mode === 'rich') {
|
|
assert.match(result.receipts[0].html, /<ul><li>Open point/);
|
|
assert.match(result.receipts[0].html, /<strong>emphasis<\/strong>/);
|
|
assert.doesNotMatch(result.receipts[0].html, /PRIVATE APP CHROME/);
|
|
}
|
|
}
|
|
}
|
|
console.log('Clipboard browser checks passed: rich HTML, plain text, blocked/manual fallback.');
|
|
} finally {
|
|
await browser.close();
|
|
}
|