PluginProbe
Extendify / 3.0.6
Extendify v3.0.6
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 / src / Agent / lib / __tests__ / variant-classes.test.js

variant-classes.test.js in Extendify 3.0.6, at src/Agent/lib/__tests__/variant-classes.test.js

476 lines 15.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import {
2 applyVariantNumberMapToHtml,
3 esc,
4 getVariantClassInfo,
5 getVariantClassInfoFromHtml,
6 getVariantNumbersInHtml,
7 getVariantNumbersInTree,
8 patchVariantClasses,
9 } from '../variant-classes';
10
11 describe('variant-classes regex patterns', () => {
12 describe('esc', () => {
13 it('escapes special regex characters', () => {
14 expect(esc('is-style-outline')).toBe('is-style-outline');
15 expect(esc('test.class')).toBe('test\\.class');
16 expect(esc('test[0]')).toBe('test\\[0\\]');
17 });
18 });
19
20 describe('getVariantNumbersInTree', () => {
21 describe('is-style-outline pattern (simple)', () => {
22 it('extracts number from is-style-outline--N', () => {
23 const el = document.createElement('div');
24 el.className = 'wp-block-button is-style-outline is-style-outline--3';
25
26 const result = getVariantNumbersInTree(el, 'is-style-outline');
27 expect(result).toEqual([3]);
28 });
29
30 it('extracts multiple numbers from nested elements', () => {
31 const el = document.createElement('div');
32 el.innerHTML = `
33 <div class="is-style-outline--1"></div>
34 <div class="is-style-outline--2"></div>
35 `;
36
37 const result = getVariantNumbersInTree(el, 'is-style-outline');
38 expect(result).toEqual([1, 2]);
39 });
40
41 it('returns empty array when no matches', () => {
42 const el = document.createElement('div');
43 el.className = 'wp-block-button is-style-outline';
44
45 const result = getVariantNumbersInTree(el, 'is-style-outline');
46 expect(result).toEqual([]);
47 });
48
49 it('deduplicates numbers', () => {
50 const el = document.createElement('div');
51 el.innerHTML = `
52 <div class="is-style-outline--1"></div>
53 <div class="is-style-outline--1"></div>
54 `;
55
56 const result = getVariantNumbersInTree(el, 'is-style-outline');
57 expect(result).toEqual([1]);
58 });
59
60 it('does not match classes without trailing number', () => {
61 const el = document.createElement('div');
62 el.className = 'is-style-outline is-style-outline-foo';
63
64 const result = getVariantNumbersInTree(el, 'is-style-outline');
65 expect(result).toEqual([]);
66 });
67 });
68
69 describe('is-style-ext-preset pattern (complex)', () => {
70 it('extracts number from complex class ending with --N', () => {
71 const el = document.createElement('div');
72 el.className =
73 'is-style-ext-preset--image--natural-1--image-1--content-bottom--13';
74
75 const result = getVariantNumbersInTree(el, 'is-style-ext-preset');
76 expect(result).toEqual([13]);
77 });
78
79 it('extracts multiple numbers from different elements', () => {
80 const el = document.createElement('div');
81 el.innerHTML = `
82 <figure class="is-style-ext-preset--image--natural-1--image-1--content-bottom--12"></figure>
83 <figure class="is-style-ext-preset--image--natural-1--image-1--content-bottom--13"></figure>
84 `;
85
86 const result = getVariantNumbersInTree(el, 'is-style-ext-preset');
87 expect(result).toEqual([12, 13]);
88 });
89
90 it('ignores classes without trailing --number', () => {
91 const el = document.createElement('div');
92 el.className = `
93 is-style-ext-preset-image-natural-1-image-1--content-bottom
94 is-style-ext-preset--image--natural-1--image-1--content-bottom
95 `;
96
97 const result = getVariantNumbersInTree(el, 'is-style-ext-preset');
98 expect(result).toEqual([]);
99 });
100
101 it('only extracts trailing number, not numbers in middle', () => {
102 const el = document.createElement('div');
103 el.className =
104 'is-style-ext-preset--image--natural-1--image-1--content-bottom--42';
105
106 const result = getVariantNumbersInTree(el, 'is-style-ext-preset');
107 expect(result).toEqual([42]);
108 });
109 });
110
111 it('returns empty array for null element', () => {
112 const result = getVariantNumbersInTree(null, 'is-style-outline');
113 expect(result).toEqual([]);
114 });
115 });
116
117 describe('getVariantNumbersInHtml', () => {
118 it('extracts numbers from HTML string', () => {
119 const html = '<div class="is-style-outline--5">Test</div>';
120
121 const result = getVariantNumbersInHtml(html, 'is-style-outline');
122 expect(result).toEqual([5]);
123 });
124
125 it('handles complex ext-preset patterns', () => {
126 const html =
127 '<figure class="is-style-ext-preset--image--natural-1--image-1--content-bottom--1"></figure>';
128
129 const result = getVariantNumbersInHtml(html, 'is-style-ext-preset');
130 expect(result).toEqual([1]);
131 });
132 });
133
134 describe('getVariantClassInfo', () => {
135 it('extracts prefix and number pairs', () => {
136 const el = document.createElement('div');
137 el.innerHTML = `
138 <figure class="is-style-ext-preset--image--natural--4"></figure>
139 <div class="is-style-ext-preset--button--solid--5"></div>
140 `;
141
142 const result = getVariantClassInfo(el, 'is-style-ext-preset');
143
144 expect(result).toEqual([
145 { prefix: 'is-style-ext-preset--image--natural', number: 4 },
146 { prefix: 'is-style-ext-preset--button--solid', number: 5 },
147 ]);
148 });
149
150 it('extracts prefix for simple patterns', () => {
151 const el = document.createElement('div');
152 el.innerHTML = `
153 <div class="is-style-outline--3"></div>
154 <div class="is-style-outline--7"></div>
155 `;
156
157 const result = getVariantClassInfo(el, 'is-style-outline');
158
159 expect(result).toEqual([
160 { prefix: 'is-style-outline', number: 3 },
161 { prefix: 'is-style-outline', number: 7 },
162 ]);
163 });
164
165 it('deduplicates by number', () => {
166 const el = document.createElement('div');
167 el.innerHTML = `
168 <div class="is-style-outline--3"></div>
169 <div class="is-style-outline--3"></div>
170 `;
171
172 const result = getVariantClassInfo(el, 'is-style-outline');
173 expect(result).toHaveLength(1);
174 expect(result[0].number).toBe(3);
175 });
176
177 it('returns empty array for null element', () => {
178 expect(getVariantClassInfo(null, 'is-style-outline')).toEqual([]);
179 });
180
181 it('returns empty array when no matches', () => {
182 const el = document.createElement('div');
183 el.className = 'wp-block-button';
184
185 const result = getVariantClassInfo(el, 'is-style-outline');
186 expect(result).toEqual([]);
187 });
188 });
189
190 describe('getVariantClassInfoFromHtml', () => {
191 it('extracts prefix and number pairs from HTML string', () => {
192 const html = `
193 <figure class="is-style-ext-preset--image--x--4"></figure>
194 <div class="is-style-ext-preset--button--y--5"></div>
195 `;
196
197 const result = getVariantClassInfoFromHtml(html, 'is-style-ext-preset');
198
199 expect(result).toEqual([
200 { prefix: 'is-style-ext-preset--image--x', number: 4 },
201 { prefix: 'is-style-ext-preset--button--y', number: 5 },
202 ]);
203 });
204
205 it('handles simple patterns', () => {
206 const html = '<div class="is-style-outline--5">Test</div>';
207
208 const result = getVariantClassInfoFromHtml(html, 'is-style-outline');
209
210 expect(result).toEqual([{ prefix: 'is-style-outline', number: 5 }]);
211 });
212 });
213
214 describe('applyVariantNumberMapToHtml', () => {
215 describe('is-style-outline pattern', () => {
216 it('applies number mapping to simple pattern', () => {
217 const html =
218 '<div class="wp-block-button is-style-outline is-style-outline--1">Test</div>';
219 const map = new Map([[1, 5]]);
220
221 const result = applyVariantNumberMapToHtml(
222 html,
223 'is-style-outline',
224 map,
225 );
226
227 expect(result).toContain('is-style-outline--5');
228 expect(result).not.toMatch(/is-style-outline--1[^\d]/);
229 });
230
231 it('applies multiple mappings', () => {
232 const html = `
233 <div class="is-style-outline--1"></div>
234 <div class="is-style-outline--2"></div>
235 `;
236 const map = new Map([
237 [1, 10],
238 [2, 20],
239 ]);
240
241 const result = applyVariantNumberMapToHtml(
242 html,
243 'is-style-outline',
244 map,
245 );
246
247 expect(result).toContain('is-style-outline--10');
248 expect(result).toContain('is-style-outline--20');
249 });
250
251 it('returns unchanged html if map is empty', () => {
252 const html = '<div class="is-style-outline--1">Test</div>';
253 const map = new Map();
254
255 const result = applyVariantNumberMapToHtml(
256 html,
257 'is-style-outline',
258 map,
259 );
260
261 expect(result).toContain('is-style-outline--1');
262 });
263 });
264
265 describe('is-style-ext-preset pattern', () => {
266 it('applies mapping to complex pattern', () => {
267 const html =
268 '<figure class="wp-block-image is-style-ext-preset--image--natural-1--image-1--content-bottom--1"></figure>';
269 const map = new Map([[1, 12]]);
270
271 const result = applyVariantNumberMapToHtml(
272 html,
273 'is-style-ext-preset',
274 map,
275 );
276
277 expect(result).toContain(
278 'is-style-ext-preset--image--natural-1--image-1--content-bottom--12',
279 );
280 });
281
282 it('preserves middle numbers when changing trailing number', () => {
283 const html =
284 '<figure class="is-style-ext-preset--image--natural-1--image-1--content-bottom--2"></figure>';
285 const map = new Map([[2, 13]]);
286
287 const result = applyVariantNumberMapToHtml(
288 html,
289 'is-style-ext-preset',
290 map,
291 );
292
293 expect(result).toContain('--natural-1--');
294 expect(result).toContain('--image-1--');
295 expect(result).toContain('content-bottom--13');
296 });
297 });
298 });
299
300 describe('patchVariantClasses', () => {
301 describe('is-style-outline pattern', () => {
302 it('patches HTML to match DOM variant numbers', () => {
303 const html =
304 '<div class="wp-block-button is-style-outline is-style-outline--1">Test</div>';
305 const el = document.createElement('div');
306 el.className = 'wp-block-button is-style-outline is-style-outline--5';
307
308 const result = patchVariantClasses(html, el, ['is-style-outline']);
309
310 expect(result).toContain('is-style-outline--5');
311 });
312
313 it('handles multiple variant numbers', () => {
314 const html = `
315 <div class="is-style-outline--1"></div>
316 <div class="is-style-outline--2"></div>
317 `;
318 const el = document.createElement('div');
319 el.innerHTML = `
320 <div class="is-style-outline--10"></div>
321 <div class="is-style-outline--20"></div>
322 `;
323
324 const result = patchVariantClasses(html, el, ['is-style-outline']);
325
326 expect(result).toContain('is-style-outline--10');
327 expect(result).toContain('is-style-outline--20');
328 });
329
330 it('returns unchanged HTML if no target numbers', () => {
331 const html = '<div class="is-style-outline--1">Test</div>';
332 const el = document.createElement('div');
333 el.className = 'wp-block-button';
334
335 const result = patchVariantClasses(html, el, ['is-style-outline']);
336
337 expect(result).toContain('is-style-outline--1');
338 });
339 });
340
341 describe('is-style-ext-preset pattern', () => {
342 it('patches complex variant classes', () => {
343 const html =
344 '<figure class="wp-block-image is-style-ext-preset--image--natural-1--image-1--content-bottom--1"></figure>';
345 const el = document.createElement('div');
346 el.innerHTML =
347 '<figure class="is-style-ext-preset--image--natural-1--image-1--content-bottom--12"></figure>';
348
349 const result = patchVariantClasses(html, el, ['is-style-ext-preset']);
350
351 expect(result).toContain('content-bottom--12');
352 });
353
354 it('handles multiple complex variants', () => {
355 const html = `
356 <figure class="is-style-ext-preset--a--1"></figure>
357 <figure class="is-style-ext-preset--b--2"></figure>
358 `;
359 const el = document.createElement('div');
360 el.innerHTML = `
361 <figure class="is-style-ext-preset--a--12"></figure>
362 <figure class="is-style-ext-preset--b--13"></figure>
363 `;
364
365 const result = patchVariantClasses(html, el, ['is-style-ext-preset']);
366
367 expect(result).toContain('is-style-ext-preset--a--12');
368 expect(result).toContain('is-style-ext-preset--b--13');
369 });
370
371 it('preserves non-variant classes', () => {
372 const html = `<figure class="wp-block-image is-style-ext-preset-image-natural-1-image-1--content-bottom is-style-ext-preset--image--natural-1--image-1--content-bottom is-style-ext-preset--image--natural-1--image-1--content-bottom--1"></figure>`;
373 const el = document.createElement('div');
374 el.innerHTML = `<figure class="is-style-ext-preset--image--natural-1--image-1--content-bottom--13"></figure>`;
375
376 const result = patchVariantClasses(html, el, ['is-style-ext-preset']);
377
378 // Should preserve non-variant classes
379 expect(result).toContain(
380 'is-style-ext-preset-image-natural-1-image-1--content-bottom',
381 );
382 // Should patch the variant class
383 expect(result).toContain('content-bottom--13');
384 });
385 });
386
387 describe('multiple bases', () => {
388 it('processes multiple base patterns', () => {
389 const html = `
390 <div class="is-style-outline--1"></div>
391 <div class="is-style-ext-preset--a--2"></div>
392 `;
393 const el = document.createElement('div');
394 el.innerHTML = `
395 <div class="is-style-outline--10"></div>
396 <div class="is-style-ext-preset--a--20"></div>
397 `;
398
399 const result = patchVariantClasses(html, el, [
400 'is-style-outline',
401 'is-style-ext-preset',
402 ]);
403
404 expect(result).toContain('is-style-outline--10');
405 expect(result).toContain('is-style-ext-preset--a--20');
406 });
407 });
408
409 describe('element reordering (regression tests)', () => {
410 it('matches by element type when elements are in different order than DOM', () => {
411 // HTML has image first, button second
412 const html = `
413 <figure class="is-style-ext-preset--image--x--1"></figure>
414 <div class="is-style-ext-preset--button--y--2"></div>
415 `;
416 // DOM has button first, image second (different order)
417 const el = document.createElement('div');
418 el.innerHTML = `
419 <div class="is-style-ext-preset--button--y--10"></div>
420 <figure class="is-style-ext-preset--image--x--11"></figure>
421 `;
422
423 const result = patchVariantClasses(html, el, ['is-style-ext-preset']);
424
425 // Should match by prefix (element type), not by position
426 expect(result).toContain('is-style-ext-preset--image--x--11');
427 expect(result).toContain('is-style-ext-preset--button--y--10');
428 });
429
430 it('does not swap variant numbers when elements with same numbers are swapped', () => {
431 // Original: image--4 left, button--5 right
432 // After swap: button--5 left, image--4 right
433 // The variant numbers should stay with their elements
434 const html = `
435 <div class="is-style-ext-preset--button--solid--1"></div>
436 <figure class="is-style-ext-preset--image--natural--2"></figure>
437 `;
438 const el = document.createElement('div');
439 el.innerHTML = `
440 <figure class="is-style-ext-preset--image--natural--4"></figure>
441 <div class="is-style-ext-preset--button--solid--5"></div>
442 `;
443
444 const result = patchVariantClasses(html, el, ['is-style-ext-preset']);
445
446 // Button should get 5, image should get 4 (matched by type, not position)
447 expect(result).toContain('is-style-ext-preset--button--solid--5');
448 expect(result).toContain('is-style-ext-preset--image--natural--4');
449 });
450
451 it('handles multiple elements of the same type with position-based matching within type', () => {
452 // Two images and one button
453 const html = `
454 <figure class="is-style-ext-preset--image--a--1"></figure>
455 <figure class="is-style-ext-preset--image--a--2"></figure>
456 <div class="is-style-ext-preset--button--b--3"></div>
457 `;
458 const el = document.createElement('div');
459 el.innerHTML = `
460 <figure class="is-style-ext-preset--image--a--10"></figure>
461 <figure class="is-style-ext-preset--image--a--20"></figure>
462 <div class="is-style-ext-preset--button--b--30"></div>
463 `;
464
465 const result = patchVariantClasses(html, el, ['is-style-ext-preset']);
466
467 // Images should be matched by position within the image group
468 expect(result).toContain('is-style-ext-preset--image--a--10');
469 expect(result).toContain('is-style-ext-preset--image--a--20');
470 // Button matched by its type
471 expect(result).toContain('is-style-ext-preset--button--b--30');
472 });
473 });
474 });
475 });
476