Add unit tests for new auto-link paste behavior

pull/12433/head
Thibaud Colas 2024-10-21 13:19:46 +01:00 zatwierdzone przez Sage Abdullah
rodzic ba6360446e
commit b31319934a
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: EB1A33CC51CC0217
1 zmienionych plików z 92 dodań i 2 usunięć

Wyświetl plik

@ -5,6 +5,7 @@ import {
convertFromHTML,
ContentState,
EditorState,
convertToRaw,
} from 'draft-js';
import Link, { getLinkAttributes, getValidLinkURL, onPasteLink } from './Link';
@ -136,6 +137,7 @@ describe.each`
describe('onPasteLink', () => {
let editorState;
let setEditorState;
let testOnPasteOutput;
beforeEach(() => {
const { contentBlocks } = convertFromHTML('<p>hello</p>');
@ -143,6 +145,14 @@ describe('onPasteLink', () => {
editorState = EditorState.createWithContent(contentState);
setEditorState = jest.fn((state) => state);
testOnPasteOutput = (text, html) => {
expect(onPasteLink(text, html, editorState, { setEditorState })).toBe(
'handled',
);
const content = setEditorState.mock.calls[0][0].getCurrentContent();
return convertToRaw(content);
};
});
it('discards invalid URLs', () => {
@ -152,7 +162,7 @@ describe('onPasteLink', () => {
expect(setEditorState).not.toHaveBeenCalled();
});
it('creates link onto selected text', () => {
it('single link onto selected text', () => {
const selection = editorState.getSelection().merge({
focusOffset: 4,
});
@ -171,7 +181,7 @@ describe('onPasteLink', () => {
).toBe('https://example.com/selected');
});
it('creates link with paste as link text when collapsed', () => {
it('single link without selection', () => {
expect(
onPasteLink('https://example.com/collapsed', null, editorState, {
setEditorState,
@ -186,4 +196,84 @@ describe('onPasteLink', () => {
content.getEntity(content.getLastCreatedEntityKey()).getData().url,
).toBe('https://example.com/collapsed');
});
it('multiple plain-text links and emails', () => {
const input =
'http://a.co/ ftp://b.co/ test@example.com https://c.co/ ftps://d.co';
const raw = testOnPasteOutput(input, null);
expect(raw.blocks[0]).toMatchObject({
text: `${input}hello`,
entityRanges: [
{ offset: 0, length: 12, key: 0 },
{ offset: 13, length: 11, key: 1 },
{ offset: 25, length: 16, key: 2 },
{ offset: 42, length: 13, key: 3 },
{ offset: 56, length: 11, key: 4 },
],
});
expect(raw.entityMap).toMatchObject({
0: {
type: 'LINK',
mutability: 'MUTABLE',
data: { url: 'http://a.co/' },
},
1: { data: { url: 'ftp://b.co/' } },
2: { data: { url: 'mailto:test@example.com' } },
3: { data: { url: 'https://c.co/' } },
4: { data: { url: 'ftps://d.co' } },
});
});
it('multiple URLs and emails within HTML', () => {
const input = `
<p><span>start</span></p>
<p><span>l1 http://a.co/</span></p>
<p><span>l2a test@example.com l2b</span></p>
<p><span>https://c.co/ l3</span></p>
<p><span>end</span></p>
`;
const raw = testOnPasteOutput(input.replace(/<[^>]+/g), input);
expect(raw.blocks).toMatchObject([
{ text: 'start', entityRanges: [] },
{
text: 'l1 http://a.co/',
entityRanges: [{ offset: 3, length: 12, key: 0 }],
},
{
text: 'l2a test@example.com l2b',
entityRanges: [{ offset: 4, length: 16, key: 1 }],
},
{
text: 'https://c.co/ l3',
entityRanges: [{ offset: 0, length: 13, key: 2 }],
},
{ text: 'endhello', entityRanges: [] },
]);
expect(raw.entityMap).toMatchObject({
0: { data: { url: 'http://a.co/' } },
1: { data: { url: 'mailto:test@example.com' } },
2: { data: { url: 'https://c.co/' } },
});
});
it('preserves existing rich text', () => {
const input = `
<h2><span>Heading</span></h2>
<p><span>http://a.co/</span></p>
<p><span><a href="http://test.co/">link</a></span></p>
`;
const raw = testOnPasteOutput(input.replace(/<[^>]+/g), input);
expect(raw.blocks).toMatchObject([
{ type: 'header-two', text: 'Heading', entityRanges: [] },
{
text: 'http://a.co/',
entityRanges: [{ offset: 0, length: 12, key: 0 }],
},
{ text: 'linkhello', entityRanges: [{ offset: 0, length: 4, key: 1 }] },
]);
expect(raw.entityMap).toMatchObject({
0: { data: { url: 'http://a.co/' } },
1: { data: { url: 'http://test.co/' } },
});
});
});