The word-boundary cut removed everything after '# ' when the first 500 characters were one long heading, leaving '#…'. Keep the hard cut when the soft cut would leave only a markdown marker. Review P3 on F1 (#1873).
25 lines
2.9 KiB
JavaScript
25 lines
2.9 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { fixture } from './fixture.mjs';
|
|
import { browser } from './browser.mjs';
|
|
import { P, stub } from './helpers/projects-review-fixture.mjs';
|
|
|
|
test('overview renders a safe, bounded north star markdown preview and links to Docs', { timeout: 45000 }, async t => {
|
|
const f = await fixture(), b = await browser({ machine: false });
|
|
t.after(async () => { await b.close(); await f.close(); });
|
|
const markdown = '# A clear direction\n\n<script>window.northInjected=true</script>\n\n' + 'A long goal. '.repeat(200);
|
|
const source = stub.replace('A reliable Pomodoro timer that opens locally and works offline.', markdown.replaceAll('\\', '\\\\').replaceAll("'", "\\'").replaceAll('\n', '\\n'));
|
|
await b.call('Page.addScriptToEvaluateOnNewDocument', { source });
|
|
await b.viewport(1440, 900); await b.navigate(f.base + '/#/projects/' + P);
|
|
await b.evaluate(`(async()=>{for(let i=0;i<200;i++){if(document.querySelector('[data-project-content] .project-metrics'))return;await new Promise(r=>setTimeout(r,30));}throw Error('overview did not load')})()`);
|
|
const result = await b.evaluate(`(()=>{const p=document.querySelector('[data-north-star]');return {heading:p?.querySelector('h1')?.textContent, html:p?.querySelector('script')!==null, injected:!!window.northInjected, length:p?.textContent.length, link:document.querySelector('[data-project-content] a[href="#/docs/timer/spec%2Fnorth-star.md"]')?.textContent}})()`);
|
|
assert.equal(result.heading, 'A clear direction');
|
|
assert.equal(result.html, false); assert.equal(result.injected, false);
|
|
assert.ok(result.length < 700, 'preview is bounded'); assert.equal(result.link, 'Open north star in Docs');
|
|
await b.evaluate(`{const old=window.fetch;window.fetch=(u,o)=>String(u).startsWith('/api/project-file?')?Promise.resolve(new Response(JSON.stringify({content:'# Updated direction'}),{headers:{'content-type':'application/json'}})):old(u,o);document.querySelector('#refresh').click();}`);
|
|
await b.evaluate(`(async()=>{for(let i=0;i<200;i++){if(document.querySelector('[data-north-star] h1')?.textContent==='Updated direction')return;await new Promise(r=>setTimeout(r,30));}throw Error('north star did not refresh')})()`);
|
|
// A heading longer than the preview keeps its text instead of collapsing to the marker.
|
|
await b.evaluate(`{const old=window.fetch;window.fetch=(u,o)=>String(u).startsWith('/api/project-file?')?Promise.resolve(new Response(JSON.stringify({content:'# '+'A'.repeat(600)}),{headers:{'content-type':'application/json'}})):old(u,o);document.querySelector('#refresh').click();}`);
|
|
await b.evaluate(`(async()=>{for(let i=0;i<200;i++){if((document.querySelector('[data-north-star] h1')?.textContent||'').startsWith('AAAA'))return;await new Promise(r=>setTimeout(r,30));}throw Error('long heading collapsed: '+document.querySelector('[data-north-star]')?.textContent)})()`);
|
|
});
|