@@ -29,7 +29,12 @@ const sel = {
2929 selectionStart : '[data-testid="test-links-selection-start"]' ,
3030 selectionEnd : '[data-testid="test-links-selection-end"]' ,
3131 applySelection : '[data-testid="test-links-apply-selection-button"]' ,
32+ applySetLinkFromSelection :
33+ '[data-testid="test-links-apply-setlink-from-selection-button"]' ,
34+ selectionPayload : '[data-testid="test-links-selection-payload"]' ,
3235 onLinkDetectedPayload : '[data-testid="on-link-detected-payload"]' ,
36+ onLinkPressEnabled : '[data-testid="test-links-onlinkpress-enabled"]' ,
37+ onLinkPressPayload : '[data-testid="on-link-press-payload"]' ,
3338 editorInner : '[data-testid="test-links-editor"] .eti-editor' ,
3439 editorScreenshot : '[data-testid="test-links-editor"]' ,
3540 linkRegexMode : '[data-testid="test-links-link-regex-mode"]' ,
@@ -60,6 +65,10 @@ async function getOnLinkDetectedPayload(page: Page): Promise<string> {
6065 return ( await page . locator ( sel . onLinkDetectedPayload ) . textContent ( ) ) ?? '' ;
6166}
6267
68+ async function getOnLinkPressPayload ( page : Page ) : Promise < string > {
69+ return ( await page . locator ( sel . onLinkPressPayload ) . textContent ( ) ) ?? '' ;
70+ }
71+
6372test ( 'links display visual regression' , async ( { page } ) => {
6473 await gotoVisualRegression ( page ) ;
6574 const html = [
@@ -251,6 +260,61 @@ test.describe('test-links setLink table', () => {
251260 }
252261} ) ;
253262
263+ test . describe ( 'test-links setLink round-trips onChangeSelection text' , ( ) => {
264+ test ( 'linking a selection across a block boundary keeps both paragraphs' , async ( {
265+ page,
266+ } ) => {
267+ await gotoTestLinks ( page ) ;
268+ await setTestLinksEditorHtml ( page , '<html><p>hello</p><p>world</p></html>' ) ;
269+
270+ await page . fill ( sel . selectionStart , '3' ) ;
271+ await page . fill ( sel . selectionEnd , '8' ) ;
272+ await page . fill ( sel . setLinkUrl , 'https://swmansion.com' ) ;
273+ await page . click ( sel . applySelection ) ;
274+
275+ await expect
276+ . poll ( async ( ) => page . locator ( sel . selectionPayload ) . textContent ( ) )
277+ . toBe ( JSON . stringify ( { start : 3 , end : 8 , text : 'lo\nwo' } ) ) ;
278+
279+ await page . click ( sel . applySetLinkFromSelection ) ;
280+
281+ await expect
282+ . poll ( async ( ) => getTestLinksSerializedHtml ( page ) )
283+ . toContain (
284+ '<p>hel<a href="https://swmansion.com">lo</a></p>' +
285+ '<p><a href="https://swmansion.com">wo</a>rld</p>'
286+ ) ;
287+ } ) ;
288+
289+ test ( 'linking a selection across a block boundary preserves inline marks' , async ( {
290+ page,
291+ } ) => {
292+ await gotoTestLinks ( page ) ;
293+ await setTestLinksEditorHtml (
294+ page ,
295+ '<html><p>hel<b>lo</b></p><p>world</p></html>'
296+ ) ;
297+
298+ await page . fill ( sel . selectionStart , '3' ) ;
299+ await page . fill ( sel . selectionEnd , '8' ) ;
300+ await page . fill ( sel . setLinkUrl , 'https://swmansion.com' ) ;
301+ await page . click ( sel . applySelection ) ;
302+
303+ await expect
304+ . poll ( async ( ) => page . locator ( sel . selectionPayload ) . textContent ( ) )
305+ . toBe ( JSON . stringify ( { start : 3 , end : 8 , text : 'lo\nwo' } ) ) ;
306+
307+ await page . click ( sel . applySetLinkFromSelection ) ;
308+
309+ await expect
310+ . poll ( async ( ) => getTestLinksSerializedHtml ( page ) )
311+ . toContain (
312+ '<p>hel<a href="https://swmansion.com"><b>lo</b></a></p>' +
313+ '<p><a href="https://swmansion.com">wo</a>rld</p>'
314+ ) ;
315+ } ) ;
316+ } ) ;
317+
254318test . describe ( 'test-links removeLink table' , ( ) => {
255319 const cases : {
256320 name : string ;
@@ -360,6 +424,39 @@ test.describe('test-links onLinkDetected', () => {
360424 } ) ;
361425} ) ;
362426
427+ test . describe ( 'test-links onLinkPress' , ( ) => {
428+ test ( 'clicking a link does nothing when onLinkPress is not provided' , async ( {
429+ page,
430+ } ) => {
431+ await gotoTestLinks ( page ) ;
432+ await setTestLinksEditorHtml (
433+ page ,
434+ '<html><p><a href="https://example.com">Example</a></p></html>'
435+ ) ;
436+
437+ await page . locator ( sel . editorInner ) . locator ( 'a' ) . click ( ) ;
438+
439+ await expect ( page . locator ( sel . onLinkPressPayload ) ) . toHaveText ( 'null' ) ;
440+ } ) ;
441+
442+ test ( 'clicking a link fires onLinkPress with the url when provided' , async ( {
443+ page,
444+ } ) => {
445+ await gotoTestLinks ( page ) ;
446+ await page . check ( sel . onLinkPressEnabled ) ;
447+ await setTestLinksEditorHtml (
448+ page ,
449+ '<html><p><a href="https://example.com">Example</a></p></html>'
450+ ) ;
451+
452+ await page . locator ( sel . editorInner ) . locator ( 'a' ) . click ( ) ;
453+
454+ await expect
455+ . poll ( async ( ) => getOnLinkPressPayload ( page ) )
456+ . toBe ( JSON . stringify ( { url : 'https://example.com' } ) ) ;
457+ } ) ;
458+ } ) ;
459+
363460test . describe ( 'test-links autolink' , ( ) => {
364461 async function resetEditorAndSetLinkRegexMode (
365462 page : Page ,
0 commit comments