Skip to content

Commit 790caf7

Browse files
committed
feat: update tests to use local image paths and improve error handling for image loading
1 parent bc8decd commit 790caf7

5 files changed

Lines changed: 62 additions & 33 deletions

File tree

CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,28 @@
99
> - :house: [Internal]
1010
> - :nail_care: [Polish]
1111

12+
## 4.12.36
13+
14+
#### :bug: Bug Fix
15+
16+
- **Lists / `enter: 'br'` mode**: converting a list type (`ul ↔ ol`, or applying a class/style that forces the REPLACE path) destroyed the list — `unwrapList` extracted the `li` content into a `DocumentFragment` that was dissolved on insertion, so `wrapList` received an empty detached node and the new `<ol>`/`<ul>` was never inserted into the document; the content was left as bare inline nodes. In the REPLACE path the `li` now stays in the document and is re-wrapped directly.
17+
- **commitStyle / attributes**: a `number`/`boolean` attribute value (e.g. `commitStyle({ element: 'a', attributes: { tabindex: 2 } })`) could never be toggled off — the `attr()` getter returns a string, so the strict comparison against the raw value always failed and every re-apply took the CHANGE branch instead of UNSET. The value is normalized to a string before comparison now.
18+
- **Selection**: `cursorInTheEdge()` (and its `cursorOnTheLeft`/`cursorOnTheRight` wrappers) threw `IndexSizeError` when the document had no selection ranges — `getRangeAt(0)` was called without checking `rangeCount`. It returns `null` now, as documented.
19+
- **Selection**: `eachSelection()` threw `TypeError` when the selection root was an empty editor (`childNodes[-1]` produced an `undefined` start node).
20+
- **Dom.isFragment**: fragments belonging to an inert document (`template.content`, `DOMParser` output) were not recognized because of a stale `defaultView` requirement — same class of problem already fixed for `Dom.isElement` earlier.
21+
- **Dom.between**: when `end` was an ancestor of `start`, the ascent skipped over it and the callback kept firing for nodes far outside the intended range, up to the end of the tree.
22+
- **Dom.replaceTemporaryFromString**: the regular expression hardcoded the `data-jodit-temp` attribute name instead of using the `TEMP_ATTR` constant and did not match a temporary element whose marker attribute has no value (`<span data-jodit-temp>`).
23+
- **LazyWalker**: stopping a walk did not really cancel it — `stop()` called `cancelIdleCallback` with an id that was never assigned (dead code left from the pre-`scheduler.postTask` implementation) and the scheduler's `AbortController` was never aborted. Also, `setWork()` called before the first chunk had started did not cancel the previously scheduled pass. Repeated `setWork()` calls (the `clean-html` plugin does this on every change) piled up concurrent loops pumping the same generator, defeating the chunked-walk throttling. The pending task is now aborted in `stop()`.
24+
- **LazyWalker**: the `affect` flag was not reset when a pass was interrupted via `break()`, so the next pass reported `end(affect = true)` even if it had not changed anything (a false `synchronizeValues` trigger for `clean-html`). It also processed `timeoutChunkSize + 1` nodes per chunk instead of the configured size.
25+
26+
#### :house: Internal
27+
28+
- **Dom**: the `Dom.replace(elm, 'p')` overload without a `create` instance is removed from the type surface — it always failed at runtime on an assertion (`Need create instance for new tag`); `create` is now required whenever the replacement is defined by a tag name or an HTML string. `Dom.isList` is honestly typed as `HTMLUListElement | HTMLOListElement`, `Dom.isComment` accepts `Nullable<Node>`, `isSameAttributes` no longer pretends to be a type predicate, `CommitStyle.isApplied` returns a real boolean.
29+
- **Dom**: `nextGen` builds its sibling stack with `push` + `reverse` instead of `unshift` in a loop (was O(n²) on wide sibling lists); `isTag` computes the upper-case tag name lazily; the temporary-element regexp is compiled once at the module level.
30+
- **Docs**: fixed the misleading/inverted JSDoc for `Dom.between`, `Dom.up` (root-check asymmetry), `Dom.safeInsertNode`, `LazyWalker` options and events, `cursorInTheEdgeOfString`, `isSuitElement` (`strictStyle` description was inverted), the `LazyWalker` example in the DOM module README (options object, not a number), and the `Dom.replace` example (missing `create` argument).
31+
- **Tests**: new coverage for `Dom.between`, `Dom.isFragment` (inert documents), `Dom.replace`, `Dom.replaceTemporaryFromString`, wide sibling traversal order in `Dom.find`, `LazyWalker` restart/affect-flag reset, `cursorInTheEdge` without a selection, `eachSelection` on an empty editor, `ul → ol` conversion in `enter: 'br'` mode, and toggling a numeric attribute via `commitStyle`.
32+
- **Tests / hermetic images**: the resize, image-editor and image-properties karma tests that wait for a real image load no longer fetch `https://xdsoft.net/jodit/files/artio.jpg`/`th.jpg` from the live server — they use the byte-identical `tests/artio.jpg` already served by karma, so a slow or unreachable xdsoft.net can't time these tests out anymore (~17 tests were flaking on degraded networks). The `onLoadImage` test helper now also rejects with a clear `failed to load "<src>"` message on an image `error` event instead of hanging until the mocha timeout.
33+
1234
## 4.12.35
1335

1436
#### :bug: Bug Fix

src/modules/image-editor/image-editor.test.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@
3333
disablePlugins: 'mobile'
3434
});
3535

36-
editor.value =
37-
'<img alt="" src="https://xdsoft.net/jodit/files/th.jpg">';
36+
editor.value = '<img alt="" src="tests/artio.jpg">';
3837

3938
simulateEvent(
4039
'dblclick',
@@ -146,8 +145,7 @@
146145
}
147146
});
148147

149-
editor.value =
150-
'<img alt="" src="https://xdsoft.net/jodit/files/th.jpg">';
148+
editor.value = '<img alt="" src="tests/artio.jpg">';
151149

152150
simulateEvent(
153151
'dblclick',
@@ -644,8 +642,7 @@
644642
source: 'default'
645643
});
646644

647-
editor.value =
648-
'<img alt="" src="https://xdsoft.net/jodit/files/th.jpg">';
645+
editor.value = '<img alt="" src="tests/artio.jpg">';
649646

650647
simulateEvent('dblclick', editor.editor.querySelector('img'));
651648

src/plugins/image-properties/image-properties.test.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,7 +1243,7 @@ describe('Edit image tests', () => {
12431243
describe('No available classes defined', () => {
12441244
it('Should render as input box', async () => {
12451245
const refs = await openImagePropertiesDialog(
1246-
'<p><img alt="" src="https://xdsoft.net/jodit/files/th.jpg"></p>',
1246+
'<p><img alt="" src="tests/artio.jpg"></p>',
12471247
{
12481248
history: {
12491249
timeout: 0
@@ -1263,7 +1263,7 @@ describe('Edit image tests', () => {
12631263
describe('Available classes defined', () => {
12641264
it('Should render as select box', async () => {
12651265
const refs = await openImagePropertiesDialog(
1266-
'<p><img alt="" src="https://xdsoft.net/jodit/files/th.jpg"/></p>',
1266+
'<p><img alt="" src="tests/artio.jpg"/></p>',
12671267
{
12681268
history: {
12691269
timeout: 0
@@ -1302,7 +1302,7 @@ describe('Edit image tests', () => {
13021302
describe('Opened dialog image', () => {
13031303
it('Should disable margin inputs for left, bottom, right if element has equals margins(margin:10px;)', async () => {
13041304
const refs = await openImagePropertiesDialog(
1305-
'<p><img alt="111" src="https://xdsoft.net/jodit/files/artio.jpg" style="margin:10px;border:1px solid red;width:100px;height:100px;"/></p>',
1305+
'<p><img alt="111" src="tests/artio.jpg" style="margin:10px;border:1px solid red;width:100px;height:100px;"/></p>',
13061306
{
13071307
history: {
13081308
timeout: 0
@@ -1319,7 +1319,7 @@ describe('Edit image tests', () => {
13191319

13201320
it('Should enable margin inputs for left, bottom, right if element has not equals margins(margin:10px 5px;)', async () => {
13211321
const refs = await openImagePropertiesDialog(
1322-
'<p><img alt="artio" src="https://xdsoft.net/jodit/files/artio.jpg" style="margin:10px 5px;border:1px solid red;width:100px;height:100px;"/></p>',
1322+
'<p><img alt="artio" src="tests/artio.jpg" style="margin:10px 5px;border:1px solid red;width:100px;height:100px;"/></p>',
13231323
{
13241324
history: {
13251325
timeout: 0

src/plugins/resizer/resizer.test.js

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ describe('Resize plugin', () => {
110110
'<div style="width:800px; margin:auto; border:1px solid red;">\n' +
111111
' wrong image selection\n' +
112112
' <div style="position:relative;text-align: left">\n' +
113-
' <textarea id="text__area0"> <img src="https://xdsoft.net/jodit/files/artio.jpg" style="border:1px solid red;width:100px;height:100px;"/></textarea>\n' +
113+
' <textarea id="text__area0"> <img src="tests/artio.jpg" style="border:1px solid red;width:100px;height:100px;"/></textarea>\n' +
114114
' </div>\n' +
115115
' </div>';
116116

@@ -144,7 +144,7 @@ describe('Resize plugin', () => {
144144
'<div style="width:800px; margin:auto; border:1px solid red;">\n' +
145145
' wrong image selection\n' +
146146
' <div style="position:relative;text-align: left">\n' +
147-
' <textarea id="text__area1"> &lt;img src="https://xdsoft.net/jodit/files/artio.jpg" style="border:1px solid red;width:100px;height:100px;"/&gt;</textarea>\n' +
147+
' <textarea id="text__area1"> &lt;img src="tests/artio.jpg" style="border:1px solid red;width:100px;height:100px;"/&gt;</textarea>\n' +
148148
' </div>\n' +
149149
' </div>';
150150

@@ -356,15 +356,15 @@ describe('Resize plugin', () => {
356356
});
357357

358358
editor.value =
359-
'<p><img src="https://xdsoft.net/jodit/files/artio.jpg" style="width: 301px;"/></p>';
359+
'<p><img src="tests/artio.jpg" style="width: 301px;"/></p>';
360360

361361
await onLoadImage(
362362
editor.editor.querySelector('img')
363363
);
364364
resizeImage(editor);
365365

366366
expect(sortAttributes(editor.value)).eq(
367-
'<p><img src="https://xdsoft.net/jodit/files/artio.jpg" style="height:159px;width:311px"></p>'
367+
'<p><img src="tests/artio.jpg" style="height:159px;width:311px"></p>'
368368
);
369369
});
370370

@@ -373,7 +373,7 @@ describe('Resize plugin', () => {
373373
const editor = getJodit();
374374

375375
editor.value =
376-
'<p><img src="https://xdsoft.net/jodit/files/artio.jpg" style="width: 301px;"/></p>';
376+
'<p><img src="tests/artio.jpg" style="width: 301px;"/></p>';
377377

378378
await onLoadImage(
379379
editor.editor.querySelector('img')
@@ -383,7 +383,7 @@ describe('Resize plugin', () => {
383383
resizeImage(editor);
384384

385385
expect(sortAttributes(editor.value)).eq(
386-
'<p><img src="https://xdsoft.net/jodit/files/artio.jpg" style="height:159px;width:311px"></p>'
386+
'<p><img src="tests/artio.jpg" style="height:159px;width:311px"></p>'
387387
);
388388
});
389389
});
@@ -398,7 +398,7 @@ describe('Resize plugin', () => {
398398
});
399399

400400
editor.value =
401-
'<p><img src="https://xdsoft.net/jodit/files/artio.jpg" style="width: 301px;"/></p>';
401+
'<p><img src="tests/artio.jpg" style="width: 301px;"/></p>';
402402

403403
await onLoadImage(
404404
editor.editor.querySelector('img')
@@ -407,7 +407,7 @@ describe('Resize plugin', () => {
407407
resizeImage(editor);
408408

409409
expect(sortAttributes(editor.value)).eq(
410-
'<p><img src="https://xdsoft.net/jodit/files/artio.jpg" style="height:159px;width:311px"></p>'
410+
'<p><img src="tests/artio.jpg" style="height:159px;width:311px"></p>'
411411
);
412412
});
413413
});
@@ -421,7 +421,7 @@ describe('Resize plugin', () => {
421421
});
422422

423423
editor.value =
424-
'<p><img src="https://xdsoft.net/jodit/files/artio.jpg" style="width: 301px;"/></p>';
424+
'<p><img src="tests/artio.jpg" style="width: 301px;"/></p>';
425425

426426
await onLoadImage(
427427
editor.editor.querySelector('img')
@@ -430,7 +430,7 @@ describe('Resize plugin', () => {
430430
resizeImage(editor);
431431

432432
expect(sortAttributes(editor.value)).eq(
433-
'<p><img src="https://xdsoft.net/jodit/files/artio.jpg" style="height:175px;width:311px"></p>'
433+
'<p><img src="tests/artio.jpg" style="height:175px;width:311px"></p>'
434434
);
435435
});
436436
});
@@ -446,15 +446,15 @@ describe('Resize plugin', () => {
446446
});
447447

448448
editor.value =
449-
'<p><img src="https://xdsoft.net/jodit/files/artio.jpg" style="width: 301px;"/></p>';
449+
'<p><img src="tests/artio.jpg" style="width: 301px;"/></p>';
450450

451451
await onLoadImage(
452452
editor.editor.querySelector('img')
453453
);
454454
resizeImage(editor);
455455

456456
expect(sortAttributes(editor.value)).eq(
457-
'<p><img src="https://xdsoft.net/jodit/files/artio.jpg" style="height:175px;width:311px"></p>'
457+
'<p><img src="tests/artio.jpg" style="height:175px;width:311px"></p>'
458458
);
459459
});
460460
});
@@ -472,15 +472,15 @@ describe('Resize plugin', () => {
472472
});
473473

474474
editor.value =
475-
'<p><img src="https://xdsoft.net/jodit/files/artio.jpg"/></p>';
475+
'<p><img src="tests/artio.jpg"/></p>';
476476

477477
await onLoadImage(
478478
editor.editor.querySelector('img')
479479
);
480480
resizeImage(editor);
481481

482482
expect(sortAttributes(editor.value)).eq(
483-
'<p><img height="287" src="https://xdsoft.net/jodit/files/artio.jpg" width="510"></p>'
483+
'<p><img height="287" src="tests/artio.jpg" width="510"></p>'
484484
);
485485
});
486486
});
@@ -498,7 +498,7 @@ describe('Resize plugin', () => {
498498
});
499499

500500
editor.value =
501-
'<p><img src="https://xdsoft.net/jodit/files/artio.jpg" style="width:300px"/></p>';
501+
'<p><img src="tests/artio.jpg" style="width:300px"/></p>';
502502

503503
await onLoadImage(
504504
editor.editor.querySelector('img')
@@ -507,7 +507,7 @@ describe('Resize plugin', () => {
507507
resizeImage(editor);
508508

509509
expect(sortAttributes(editor.value)).eq(
510-
'<p><img height="175" src="https://xdsoft.net/jodit/files/artio.jpg" style="width:310px" width="310"></p>'
510+
'<p><img height="175" src="tests/artio.jpg" style="width:310px" width="310"></p>'
511511
);
512512
});
513513
});
@@ -524,7 +524,7 @@ describe('Resize plugin', () => {
524524
});
525525

526526
editor.value =
527-
'<p><img src="https://xdsoft.net/jodit/files/artio.jpg" style="height:300px"/></p>';
527+
'<p><img src="tests/artio.jpg" style="height:300px"/></p>';
528528

529529
await onLoadImage(
530530
editor.editor.querySelector('img')
@@ -533,7 +533,7 @@ describe('Resize plugin', () => {
533533
resizeImage(editor);
534534

535535
expect(sortAttributes(editor.value)).eq(
536-
'<p><img height="306" src="https://xdsoft.net/jodit/files/artio.jpg" style="height:306px" width="544"></p>'
536+
'<p><img height="306" src="tests/artio.jpg" style="height:306px" width="544"></p>'
537537
);
538538
});
539539
});
@@ -550,7 +550,7 @@ describe('Resize plugin', () => {
550550
});
551551

552552
editor.value =
553-
'<p><img src="https://xdsoft.net/jodit/files/artio.jpg" style="width:300px;height:300px"/></p>';
553+
'<p><img src="tests/artio.jpg" style="width:300px;height:300px"/></p>';
554554

555555
await onLoadImage(
556556
editor.editor.querySelector('img')
@@ -559,7 +559,7 @@ describe('Resize plugin', () => {
559559
resizeImage(editor);
560560

561561
expect(sortAttributes(editor.value)).eq(
562-
'<p><img height="310" src="https://xdsoft.net/jodit/files/artio.jpg" style="height:310px;width:310px" width="310"></p>'
562+
'<p><img height="310" src="tests/artio.jpg" style="height:310px;width:310px" width="310"></p>'
563563
);
564564
});
565565
});
@@ -572,14 +572,14 @@ describe('Resize plugin', () => {
572572
getBox().style.width = '600px';
573573
const editor = getJodit();
574574
const image = new Image();
575-
image.src = 'https://xdsoft.net/jodit/files/artio.jpg';
575+
image.src = 'tests/artio.jpg';
576576

577577
await onLoadImage(image);
578578

579579
const ratio = image.naturalWidth / image.naturalHeight;
580580

581581
editor.value =
582-
'<p><img src="https://xdsoft.net/jodit/files/artio.jpg" style="width:500px;height: 281px;"/></p>';
582+
'<p><img src="tests/artio.jpg" style="width:500px;height: 281px;"/></p>';
583583
const img = editor.editor.querySelector('img');
584584
await onLoadImage(img);
585585

test/bootstrap.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1267,12 +1267,22 @@ function one(event, element, callback) {
12671267
* @param {Function} callback
12681268
*/
12691269
function onLoadImage(image, callback = () => {}) {
1270-
return new naturalPromise(resolve => {
1270+
return new naturalPromise((resolve, reject) => {
12711271
if (!image.complete) {
12721272
one('load', image, () => {
12731273
callback.call(image);
12741274
resolve();
12751275
});
1276+
1277+
// fail fast with a clear message instead of hanging until
1278+
// the mocha timeout
1279+
one('error', image, () => {
1280+
const error = new Error(
1281+
'onLoadImage: failed to load "' + image.src + '"'
1282+
);
1283+
console.warn(error.message);
1284+
reject(error);
1285+
});
12761286
} else {
12771287
callback.call(image);
12781288
resolve();

0 commit comments

Comments
 (0)