fix(onchange): support data-mutation-free on attributes chane (#2393)

This commit is contained in:
Peter Savchenko 2023-06-22 20:42:14 +03:00 committed by GitHub
parent c8993332e3
commit 9e64003c0a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 3 deletions

View file

@ -1,8 +1,12 @@
# Changelog
### 2.27.2
- `Fix` - `onChange` won't be called when element with data-mutation-free changes some attribute
### 2.27.1
- `Fix` - `onChange` will be called on removing the whole text in the last block
- `Fix` - `onChange` will be called on removing the whole text in a block
### 2.27.0

View file

@ -1,6 +1,6 @@
{
"name": "@editorjs/editorjs",
"version": "2.27.1",
"version": "2.27.2",
"description": "Editor.js — Native JS, based on API and Open Source",
"main": "dist/editorjs.umd.js",
"module": "dist/editorjs.mjs",

View file

@ -878,10 +878,11 @@ export default class Block extends EventsDispatcher<BlockEvents> {
* we should fire 'didMutated' event in that case
*/
const everyRecordIsMutationFree = mutationsOrInputEvent.length > 0 && mutationsOrInputEvent.every((record) => {
const { addedNodes, removedNodes } = record;
const { addedNodes, removedNodes, target } = record;
const changedNodes = [
...Array.from(addedNodes),
...Array.from(removedNodes),
target,
];
return changedNodes.some((node) => {

View file

@ -509,4 +509,70 @@ describe('onChange callback', () => {
},
}));
});
it('should not be fired when element with the "data-mutation-free" mark changes some attribute', () => {
/**
* Mock for tool wrapper which we will mutate in a test
*/
const toolWrapper = document.createElement('div');
/**
* Mark it as mutation-free
*/
toolWrapper.dataset.mutationFree = 'true';
/**
* Mock of tool with data-mutation-free attribute
*/
class ToolWithMutationFreeAttribute {
/**
* Simply return mocked element
*/
public render(): HTMLElement {
return toolWrapper;
}
/**
* Saving logic is not necessary for this test
*/
// eslint-disable-next-line @typescript-eslint/no-empty-function
public save(): void {}
}
const editorConfig = {
tools: {
testTool: ToolWithMutationFreeAttribute,
},
onChange: (api, event): void => {
console.log('something changed', event);
},
data: {
blocks: [
{
type: 'testTool',
data: {},
},
],
},
};
cy.spy(editorConfig, 'onChange').as('onChange');
cy.createEditor(editorConfig).as('editorInstance');
/**
* Emulate tool's internal attribute mutation
*/
// eslint-disable-next-line cypress/no-unnecessary-waiting, @typescript-eslint/no-magic-numbers
cy.wait(100).then(() => {
toolWrapper.setAttribute('some-changed-attr', 'some-new-value');
});
/**
* Check that onChange callback was not called
*/
// eslint-disable-next-line cypress/no-unnecessary-waiting, @typescript-eslint/no-magic-numbers
cy.wait(500).then(() => {
cy.get('@onChange').should('have.callCount', 0);
});
});
});