Skip to content

Commit

Permalink
fix(onchange): support data-mutation-free on attributes chane (codex-…
Browse files Browse the repository at this point in the history
  • Loading branch information
neSpecc authored Jun 22, 2023
1 parent c899333 commit 9e64003
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 3 deletions.
6 changes: 5 additions & 1 deletion docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
3 changes: 2 additions & 1 deletion src/components/block/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
66 changes: 66 additions & 0 deletions test/cypress/tests/onchange.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});
});

0 comments on commit 9e64003

Please sign in to comment.