PluginProbe
Extendify / 3.1.1
Extendify v3.1.1
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
extendify / tests / unit / QuickEdit / lib / fingerprint.test.js

fingerprint.test.js in Extendify 3.1.1, at tests/unit/QuickEdit/lib/fingerprint.test.js

82 lines 3.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 // The content fingerprint is the client half of the same-type misresolve
2 // guard (SaveController / WPNavigationController). It carries the visible text
3 // of the block the user actually clicked so the server can refuse a save that
4 // resolved — by count — to a different block of the same type. normalizeText
5 // must mirror BlockFingerprint::normalize on the PHP side.
6
7 import {
8 normalizedTextEquals,
9 normalizeText,
10 textFingerprint,
11 } from '@quick-edit/lib/fingerprint';
12
13 describe('normalizeText', () => {
14 it('collapses whitespace runs to single spaces and trims', () => {
15 expect(normalizeText(' hello world \n')).toBe('hello world');
16 });
17
18 it('treats null/undefined as empty', () => {
19 expect(normalizeText(null)).toBe('');
20 expect(normalizeText(undefined)).toBe('');
21 });
22
23 // the_content runs wptexturize on the rendered DOM the client reads, so a
24 // straight-quote source renders with smart quotes / dashes / ellipsis. Fold
25 // them back so the fingerprint matches the raw markup the server parses.
26 it('folds smart quotes, dashes, and ellipsis (wptexturize tolerance)', () => {
27 expect(normalizeText('Woody’s')).toBe("Woody's");
28 expect(normalizeText('‘a’')).toBe("'a'");
29 expect(normalizeText('“quoted”')).toBe('"quoted"');
30 expect(normalizeText('a—b')).toBe('a-b');
31 expect(normalizeText('a–b')).toBe('a-b');
32 expect(normalizeText('a--b')).toBe('a-b');
33 expect(normalizeText('more…')).toBe('more...');
34 expect(normalizeText('a b')).toBe('a b');
35 });
36 });
37
38 describe('normalizedTextEquals', () => {
39 // The reveal poll reads the editable (raw, straight quote) and the live
40 // element (rendered, wptexturize'd curly quote); the two must compare equal
41 // or a smart-quote block strands the reveal on its frame-cap.
42 it('matches a raw block against its wptexturize-rendered twin', () => {
43 expect(
44 normalizedTextEquals(
45 "Authentic falafel celebrating Chicago's vibrant food scene.",
46 'Authentic falafel celebrating Chicago’s vibrant food scene.',
47 ),
48 ).toBe(true);
49 });
50
51 it('still matches across whitespace differences', () => {
52 expect(normalizedTextEquals(' Shop Desks ', 'Shop Desks')).toBe(true);
53 });
54
55 it('treats two empty/blank texts as equal (an empty block being edited)', () => {
56 expect(normalizedTextEquals('', ' ')).toBe(true);
57 expect(normalizedTextEquals(null, undefined)).toBe(true);
58 });
59
60 it('does not match genuinely different text', () => {
61 expect(normalizedTextEquals('Welcome to WordPress', 'Shop Desks')).toBe(
62 false,
63 );
64 });
65 });
66
67 describe('textFingerprint', () => {
68 it('returns the normalized textContent of the element', () => {
69 const el = document.createElement('p');
70 el.textContent = ' Buy now ';
71 expect(textFingerprint(el)).toEqual({ text: 'Buy now' });
72 });
73
74 it('returns null when the element has no visible text (fail open)', () => {
75 expect(textFingerprint(document.createElement('figure'))).toBeNull();
76 });
77
78 it('returns null for a missing element', () => {
79 expect(textFingerprint(null)).toBeNull();
80 });
81 });
82