@elementor/editor-ui 3.33.0-207 → 3.33.0-209
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js
CHANGED
|
@@ -676,13 +676,13 @@ var useEditable = ({ value, onSubmit, validation, onClick, onError }) => {
|
|
|
676
676
|
setIsEditing(true);
|
|
677
677
|
};
|
|
678
678
|
const closeEditMode = () => {
|
|
679
|
-
ref.current?.blur();
|
|
680
679
|
setError(null);
|
|
681
680
|
onError?.(null);
|
|
682
681
|
setIsEditing(false);
|
|
683
682
|
};
|
|
684
683
|
const submit = (newValue) => {
|
|
685
684
|
if (!isDirty(newValue)) {
|
|
685
|
+
closeEditMode();
|
|
686
686
|
return;
|
|
687
687
|
}
|
|
688
688
|
if (!error) {
|
|
@@ -708,7 +708,9 @@ var useEditable = ({ value, onSubmit, validation, onClick, onError }) => {
|
|
|
708
708
|
}
|
|
709
709
|
if (["Enter"].includes(event.key)) {
|
|
710
710
|
event.preventDefault();
|
|
711
|
-
|
|
711
|
+
if (!error) {
|
|
712
|
+
ref.current?.blur();
|
|
713
|
+
}
|
|
712
714
|
}
|
|
713
715
|
};
|
|
714
716
|
const handleClick = (event) => {
|
|
@@ -717,11 +719,18 @@ var useEditable = ({ value, onSubmit, validation, onClick, onError }) => {
|
|
|
717
719
|
}
|
|
718
720
|
onClick?.(event);
|
|
719
721
|
};
|
|
722
|
+
const handleBlur = () => {
|
|
723
|
+
if (error) {
|
|
724
|
+
closeEditMode();
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
submit(ref.current.innerText);
|
|
728
|
+
};
|
|
720
729
|
const listeners = {
|
|
721
730
|
onClick: handleClick,
|
|
722
731
|
onKeyDown: handleKeyDown,
|
|
723
732
|
onInput: onChange,
|
|
724
|
-
onBlur:
|
|
733
|
+
onBlur: handleBlur
|
|
725
734
|
};
|
|
726
735
|
const attributes = {
|
|
727
736
|
value,
|
package/dist/index.mjs
CHANGED
|
@@ -647,13 +647,13 @@ var useEditable = ({ value, onSubmit, validation, onClick, onError }) => {
|
|
|
647
647
|
setIsEditing(true);
|
|
648
648
|
};
|
|
649
649
|
const closeEditMode = () => {
|
|
650
|
-
ref.current?.blur();
|
|
651
650
|
setError(null);
|
|
652
651
|
onError?.(null);
|
|
653
652
|
setIsEditing(false);
|
|
654
653
|
};
|
|
655
654
|
const submit = (newValue) => {
|
|
656
655
|
if (!isDirty(newValue)) {
|
|
656
|
+
closeEditMode();
|
|
657
657
|
return;
|
|
658
658
|
}
|
|
659
659
|
if (!error) {
|
|
@@ -679,7 +679,9 @@ var useEditable = ({ value, onSubmit, validation, onClick, onError }) => {
|
|
|
679
679
|
}
|
|
680
680
|
if (["Enter"].includes(event.key)) {
|
|
681
681
|
event.preventDefault();
|
|
682
|
-
|
|
682
|
+
if (!error) {
|
|
683
|
+
ref.current?.blur();
|
|
684
|
+
}
|
|
683
685
|
}
|
|
684
686
|
};
|
|
685
687
|
const handleClick = (event) => {
|
|
@@ -688,11 +690,18 @@ var useEditable = ({ value, onSubmit, validation, onClick, onError }) => {
|
|
|
688
690
|
}
|
|
689
691
|
onClick?.(event);
|
|
690
692
|
};
|
|
693
|
+
const handleBlur = () => {
|
|
694
|
+
if (error) {
|
|
695
|
+
closeEditMode();
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
submit(ref.current.innerText);
|
|
699
|
+
};
|
|
691
700
|
const listeners = {
|
|
692
701
|
onClick: handleClick,
|
|
693
702
|
onKeyDown: handleKeyDown,
|
|
694
703
|
onInput: onChange,
|
|
695
|
-
onBlur:
|
|
704
|
+
onBlur: handleBlur
|
|
696
705
|
};
|
|
697
706
|
const attributes = {
|
|
698
707
|
value,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-ui",
|
|
3
3
|
"description": "Elementor Editor UI",
|
|
4
|
-
"version": "3.33.0-
|
|
4
|
+
"version": "3.33.0-209",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Elementor Team",
|
|
7
7
|
"homepage": "https://elementor.com/",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"react-dom": "^18.3.1"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@elementor/editor-v1-adapters": "3.33.0-
|
|
40
|
+
"@elementor/editor-v1-adapters": "3.33.0-209",
|
|
41
41
|
"@elementor/icons": "1.53.0",
|
|
42
42
|
"@elementor/ui": "1.36.15",
|
|
43
43
|
"@tanstack/react-virtual": "^3.13.3",
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
3
|
+
|
|
4
|
+
import { EditableField } from '../../components/editable-field';
|
|
5
|
+
import { useEditable } from '../use-editable';
|
|
6
|
+
|
|
7
|
+
// Test utility component that uses the hook with EditableField
|
|
8
|
+
const TestComponent = ( {
|
|
9
|
+
value,
|
|
10
|
+
onSubmit,
|
|
11
|
+
validation,
|
|
12
|
+
onClick,
|
|
13
|
+
onError,
|
|
14
|
+
}: {
|
|
15
|
+
value: string;
|
|
16
|
+
onSubmit: ( value: string ) => unknown;
|
|
17
|
+
validation?: ( value: string ) => string | null;
|
|
18
|
+
onClick?: ( event: React.MouseEvent< HTMLDivElement > ) => void;
|
|
19
|
+
onError?: ( error: string | null ) => void;
|
|
20
|
+
} ) => {
|
|
21
|
+
const { ref, isEditing, openEditMode, error, getProps } = useEditable( {
|
|
22
|
+
value,
|
|
23
|
+
onSubmit,
|
|
24
|
+
validation,
|
|
25
|
+
onClick,
|
|
26
|
+
onError,
|
|
27
|
+
} );
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div>
|
|
31
|
+
<button onClick={ openEditMode } data-testid="open-edit">
|
|
32
|
+
Open Edit
|
|
33
|
+
</button>
|
|
34
|
+
<EditableField ref={ ref } { ...getProps() } data-testid="editable-field" />
|
|
35
|
+
<div data-testid="editing-state">{ isEditing ? 'editing' : 'not-editing' }</div>
|
|
36
|
+
<div data-testid="error-state">{ error || 'no-error' }</div>
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
describe( 'useEditable', () => {
|
|
42
|
+
it( 'should return editable content attributes and handlers', () => {
|
|
43
|
+
// Arrange & Act.
|
|
44
|
+
render( <TestComponent value="" onSubmit={ jest.fn() } /> );
|
|
45
|
+
|
|
46
|
+
// Assert.
|
|
47
|
+
const editableField = screen.getByRole( 'textbox' );
|
|
48
|
+
|
|
49
|
+
expect( editableField ).toHaveAttribute( 'role', 'textbox' );
|
|
50
|
+
expect( editableField ).toHaveAttribute( 'contentEditable', 'false' );
|
|
51
|
+
expect( editableField ).toHaveTextContent( '' );
|
|
52
|
+
} );
|
|
53
|
+
|
|
54
|
+
it( 'should set editable to true', () => {
|
|
55
|
+
// Arrange & Act.
|
|
56
|
+
render( <TestComponent value="" onSubmit={ jest.fn() } /> );
|
|
57
|
+
|
|
58
|
+
// Assert.
|
|
59
|
+
const editableField = screen.getByRole( 'textbox' );
|
|
60
|
+
const editingState = screen.getByText( 'not-editing' );
|
|
61
|
+
const openEditButton = screen.getByRole( 'button', { name: 'Open Edit' } );
|
|
62
|
+
|
|
63
|
+
expect( editingState ).toHaveTextContent( 'not-editing' );
|
|
64
|
+
expect( editableField ).toHaveAttribute( 'contentEditable', 'false' );
|
|
65
|
+
|
|
66
|
+
// Act.
|
|
67
|
+
fireEvent.click( openEditButton );
|
|
68
|
+
|
|
69
|
+
// Assert.
|
|
70
|
+
expect( screen.getByText( 'editing' ) ).toBeInTheDocument();
|
|
71
|
+
expect( editableField ).toHaveAttribute( 'contentEditable', 'true' );
|
|
72
|
+
} );
|
|
73
|
+
|
|
74
|
+
it( 'should call onSubmit with the new value on enter', async () => {
|
|
75
|
+
// Arrange.
|
|
76
|
+
const onSubmit = jest.fn();
|
|
77
|
+
const newValue = 'New value';
|
|
78
|
+
const validation = jest.fn().mockReturnValue( null );
|
|
79
|
+
|
|
80
|
+
render( <TestComponent value={ 'Some value' } onSubmit={ onSubmit } validation={ validation } /> );
|
|
81
|
+
|
|
82
|
+
const editableField = screen.getByRole( 'textbox' );
|
|
83
|
+
const openEditButton = screen.getByRole( 'button', { name: 'Open Edit' } );
|
|
84
|
+
|
|
85
|
+
// Mock the blur method to trigger onBlur event
|
|
86
|
+
mockBlur( editableField );
|
|
87
|
+
|
|
88
|
+
// Act.
|
|
89
|
+
fireEvent.click( openEditButton );
|
|
90
|
+
|
|
91
|
+
fireEvent.input( editableField, { target: { innerText: newValue } } );
|
|
92
|
+
|
|
93
|
+
// Assert.
|
|
94
|
+
expect( validation ).toHaveBeenCalledWith( newValue );
|
|
95
|
+
|
|
96
|
+
// Act.
|
|
97
|
+
fireEvent.keyDown( editableField, { key: 'Enter' } );
|
|
98
|
+
|
|
99
|
+
// Assert.
|
|
100
|
+
await waitFor( () => {
|
|
101
|
+
expect( onSubmit ).toHaveBeenCalledWith( newValue );
|
|
102
|
+
} );
|
|
103
|
+
} );
|
|
104
|
+
|
|
105
|
+
it( 'should remove the editable content attribute on blur', () => {
|
|
106
|
+
// Arrange & Act.
|
|
107
|
+
render( <TestComponent value="" onSubmit={ jest.fn() } /> );
|
|
108
|
+
|
|
109
|
+
fireEvent.click( screen.getByRole( 'button', { name: 'Open Edit' } ) );
|
|
110
|
+
|
|
111
|
+
// Assert.
|
|
112
|
+
expect( screen.getByText( 'editing' ) ).toBeInTheDocument();
|
|
113
|
+
|
|
114
|
+
// Act.
|
|
115
|
+
fireEvent.blur( screen.getByRole( 'textbox' ) );
|
|
116
|
+
|
|
117
|
+
// Assert.
|
|
118
|
+
expect( screen.getByText( 'not-editing' ) ).toBeInTheDocument();
|
|
119
|
+
} );
|
|
120
|
+
|
|
121
|
+
it( 'should call onSubmit with the new value on blur', () => {
|
|
122
|
+
// Arrange.
|
|
123
|
+
const onSubmit = jest.fn();
|
|
124
|
+
const newValue = 'New value';
|
|
125
|
+
const validation = jest.fn().mockReturnValue( null );
|
|
126
|
+
|
|
127
|
+
render( <TestComponent value={ 'Some value' } onSubmit={ onSubmit } validation={ validation } /> );
|
|
128
|
+
|
|
129
|
+
const editableField = screen.getByRole( 'textbox' );
|
|
130
|
+
|
|
131
|
+
// Act.
|
|
132
|
+
fireEvent.click( screen.getByRole( 'button', { name: 'Open Edit' } ) );
|
|
133
|
+
|
|
134
|
+
fireEvent.input( editableField, { target: { innerText: newValue } } );
|
|
135
|
+
|
|
136
|
+
// Assert.
|
|
137
|
+
expect( validation ).toHaveBeenCalledWith( newValue );
|
|
138
|
+
|
|
139
|
+
// Act.
|
|
140
|
+
fireEvent.blur( editableField );
|
|
141
|
+
|
|
142
|
+
// Assert.
|
|
143
|
+
expect( onSubmit ).toHaveBeenCalledWith( newValue );
|
|
144
|
+
} );
|
|
145
|
+
|
|
146
|
+
it( 'should set error message id validation fails on enter, and keep the edit mode open', () => {
|
|
147
|
+
// Arrange.
|
|
148
|
+
const newValue = 'invalid-value';
|
|
149
|
+
const onSubmit = jest.fn();
|
|
150
|
+
|
|
151
|
+
const validation = ( v: string ) => {
|
|
152
|
+
if ( v === newValue ) {
|
|
153
|
+
return 'Nope';
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return null;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
render( <TestComponent value={ 'Some value' } onSubmit={ onSubmit } validation={ validation } /> );
|
|
160
|
+
|
|
161
|
+
// Act.
|
|
162
|
+
fireEvent.click( screen.getByRole( 'button', { name: 'Open Edit' } ) );
|
|
163
|
+
|
|
164
|
+
// Assert.
|
|
165
|
+
expect( screen.getByText( 'no-error' ) ).toBeInTheDocument();
|
|
166
|
+
|
|
167
|
+
// Act.
|
|
168
|
+
const editableField = screen.getByRole( 'textbox' );
|
|
169
|
+
fireEvent.input( editableField, { target: { innerText: newValue } } );
|
|
170
|
+
|
|
171
|
+
// Assert.
|
|
172
|
+
expect( screen.getByText( 'Nope' ) ).toBeInTheDocument();
|
|
173
|
+
|
|
174
|
+
// Act.
|
|
175
|
+
fireEvent.keyDown( editableField, { key: 'Enter' } );
|
|
176
|
+
|
|
177
|
+
// Assert.
|
|
178
|
+
expect( onSubmit ).not.toHaveBeenCalled();
|
|
179
|
+
expect( editableField ).toHaveAttribute( 'contentEditable', 'true' );
|
|
180
|
+
} );
|
|
181
|
+
|
|
182
|
+
it( 'should not run validation & submit if the value has not changed', () => {
|
|
183
|
+
// Arrange.
|
|
184
|
+
const value = 'initial value';
|
|
185
|
+
const onSubmit = jest.fn();
|
|
186
|
+
|
|
187
|
+
const validation = () => {
|
|
188
|
+
return 'test-error';
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
render( <TestComponent value={ value } onSubmit={ onSubmit } validation={ validation } /> );
|
|
192
|
+
|
|
193
|
+
const editableField = screen.getByRole( 'textbox' );
|
|
194
|
+
const openEditButton = screen.getByRole( 'button', { name: 'Open Edit' } );
|
|
195
|
+
|
|
196
|
+
// Act.
|
|
197
|
+
fireEvent.click( openEditButton );
|
|
198
|
+
|
|
199
|
+
// Assert.
|
|
200
|
+
expect( screen.getByText( 'no-error' ) ).toBeInTheDocument();
|
|
201
|
+
|
|
202
|
+
// Act.
|
|
203
|
+
fireEvent.input( editableField, { target: { innerText: 'new value' } } );
|
|
204
|
+
|
|
205
|
+
// Assert.
|
|
206
|
+
expect( screen.getByText( 'test-error' ) ).toBeInTheDocument();
|
|
207
|
+
|
|
208
|
+
// Act.
|
|
209
|
+
fireEvent.input( editableField, { target: { innerText: value } } );
|
|
210
|
+
|
|
211
|
+
// Assert.
|
|
212
|
+
expect( screen.getByText( 'no-error' ) ).toBeInTheDocument();
|
|
213
|
+
|
|
214
|
+
// Act.
|
|
215
|
+
fireEvent.keyDown( editableField, { key: 'Enter' } );
|
|
216
|
+
|
|
217
|
+
// Assert.
|
|
218
|
+
expect( onSubmit ).not.toHaveBeenCalled();
|
|
219
|
+
} );
|
|
220
|
+
|
|
221
|
+
it( 'should not submit, and only close the edit mode on blur if there is an error', () => {
|
|
222
|
+
// Arrange.
|
|
223
|
+
const onSubmit = jest.fn();
|
|
224
|
+
const newValue = 'invalid-value';
|
|
225
|
+
const validation = jest.fn().mockReturnValue( 'Nope' );
|
|
226
|
+
|
|
227
|
+
render( <TestComponent value={ 'Some value' } onSubmit={ onSubmit } validation={ validation } /> );
|
|
228
|
+
|
|
229
|
+
const editableField = screen.getByRole( 'textbox' );
|
|
230
|
+
const openEditButton = screen.getByRole( 'button', { name: 'Open Edit' } );
|
|
231
|
+
|
|
232
|
+
// Act.
|
|
233
|
+
fireEvent.click( openEditButton );
|
|
234
|
+
|
|
235
|
+
fireEvent.input( editableField, { target: { innerText: newValue } } );
|
|
236
|
+
|
|
237
|
+
// Assert.
|
|
238
|
+
expect( validation ).toHaveBeenCalledWith( newValue );
|
|
239
|
+
|
|
240
|
+
// Act.
|
|
241
|
+
fireEvent.blur( editableField );
|
|
242
|
+
|
|
243
|
+
// Assert.
|
|
244
|
+
expect( onSubmit ).not.toHaveBeenCalled();
|
|
245
|
+
expect( screen.getByText( 'not-editing' ) ).toBeInTheDocument();
|
|
246
|
+
} );
|
|
247
|
+
} );
|
|
248
|
+
|
|
249
|
+
function mockBlur( element: HTMLElement ) {
|
|
250
|
+
const originalBlur = element.blur;
|
|
251
|
+
element.blur = jest.fn( () => {
|
|
252
|
+
originalBlur.call( element );
|
|
253
|
+
fireEvent.blur( element );
|
|
254
|
+
} );
|
|
255
|
+
}
|
|
@@ -21,8 +21,6 @@ export const useEditable = ( { value, onSubmit, validation, onClick, onError }:
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
const closeEditMode = () => {
|
|
24
|
-
ref.current?.blur();
|
|
25
|
-
|
|
26
24
|
setError( null );
|
|
27
25
|
onError?.( null );
|
|
28
26
|
setIsEditing( false );
|
|
@@ -30,6 +28,7 @@ export const useEditable = ( { value, onSubmit, validation, onClick, onError }:
|
|
|
30
28
|
|
|
31
29
|
const submit = ( newValue: string ) => {
|
|
32
30
|
if ( ! isDirty( newValue ) ) {
|
|
31
|
+
closeEditMode();
|
|
33
32
|
return;
|
|
34
33
|
}
|
|
35
34
|
|
|
@@ -62,7 +61,10 @@ export const useEditable = ( { value, onSubmit, validation, onClick, onError }:
|
|
|
62
61
|
|
|
63
62
|
if ( [ 'Enter' ].includes( event.key ) ) {
|
|
64
63
|
event.preventDefault();
|
|
65
|
-
|
|
64
|
+
// submission is invoked only on blur, to avoid issues with double-submission in certain cases
|
|
65
|
+
if ( ! error ) {
|
|
66
|
+
ref.current?.blur();
|
|
67
|
+
}
|
|
66
68
|
}
|
|
67
69
|
};
|
|
68
70
|
|
|
@@ -74,11 +76,20 @@ export const useEditable = ( { value, onSubmit, validation, onClick, onError }:
|
|
|
74
76
|
onClick?.( event );
|
|
75
77
|
};
|
|
76
78
|
|
|
79
|
+
const handleBlur = () => {
|
|
80
|
+
if ( error ) {
|
|
81
|
+
closeEditMode();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
submit( ( ref.current as HTMLElement ).innerText );
|
|
86
|
+
};
|
|
87
|
+
|
|
77
88
|
const listeners = {
|
|
78
89
|
onClick: handleClick,
|
|
79
90
|
onKeyDown: handleKeyDown,
|
|
80
91
|
onInput: onChange,
|
|
81
|
-
onBlur:
|
|
92
|
+
onBlur: handleBlur,
|
|
82
93
|
} as const;
|
|
83
94
|
|
|
84
95
|
const attributes = {
|
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
import { act, renderHook } from '@testing-library/react';
|
|
2
|
-
|
|
3
|
-
import { useEditable } from '../use-editable';
|
|
4
|
-
|
|
5
|
-
describe( 'useEditable', () => {
|
|
6
|
-
it( 'should return editable content attributes and handlers', () => {
|
|
7
|
-
// Arrange & Act.
|
|
8
|
-
const { result } = renderHook( () =>
|
|
9
|
-
useEditable( {
|
|
10
|
-
value: '',
|
|
11
|
-
onSubmit: jest.fn(),
|
|
12
|
-
} )
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
const props = result.current.getProps();
|
|
16
|
-
|
|
17
|
-
// Assert.
|
|
18
|
-
expect( props ).toEqual( {
|
|
19
|
-
value: '',
|
|
20
|
-
role: 'textbox',
|
|
21
|
-
contentEditable: false,
|
|
22
|
-
suppressContentEditableWarning: undefined,
|
|
23
|
-
onBlur: expect.any( Function ),
|
|
24
|
-
onClick: expect.any( Function ),
|
|
25
|
-
onInput: expect.any( Function ),
|
|
26
|
-
onKeyDown: expect.any( Function ),
|
|
27
|
-
} );
|
|
28
|
-
} );
|
|
29
|
-
|
|
30
|
-
it( 'should set editable to true', () => {
|
|
31
|
-
// Arrange & Act.
|
|
32
|
-
const { result } = renderHook( () => useEditable( { value: '', onSubmit: jest.fn() } ) );
|
|
33
|
-
|
|
34
|
-
// Assert.
|
|
35
|
-
expect( result.current.isEditing ).toBe( false );
|
|
36
|
-
|
|
37
|
-
// Act.
|
|
38
|
-
act( result.current.openEditMode );
|
|
39
|
-
|
|
40
|
-
// Assert.
|
|
41
|
-
expect( result.current.isEditing ).toBe( true );
|
|
42
|
-
expect( result.current.getProps() ).toMatchObject( {
|
|
43
|
-
contentEditable: true,
|
|
44
|
-
suppressContentEditableWarning: true,
|
|
45
|
-
} );
|
|
46
|
-
} );
|
|
47
|
-
|
|
48
|
-
it( 'should call onSubmit with the new value on enter', async () => {
|
|
49
|
-
// Arrange.
|
|
50
|
-
const onSubmit = jest.fn();
|
|
51
|
-
const value = 'Some value';
|
|
52
|
-
const newValue = 'New value';
|
|
53
|
-
const validation = jest.fn();
|
|
54
|
-
|
|
55
|
-
// Act.
|
|
56
|
-
const { result } = renderHook( () =>
|
|
57
|
-
useEditable( {
|
|
58
|
-
value,
|
|
59
|
-
onSubmit,
|
|
60
|
-
validation,
|
|
61
|
-
} )
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
act( () => {
|
|
65
|
-
result.current.openEditMode();
|
|
66
|
-
result.current.getProps().onInput( { target: { innerText: newValue } } as never );
|
|
67
|
-
} );
|
|
68
|
-
|
|
69
|
-
// Assert.
|
|
70
|
-
expect( validation ).toHaveBeenCalledWith( newValue );
|
|
71
|
-
|
|
72
|
-
// Act.
|
|
73
|
-
const { onKeyDown } = result.current.getProps();
|
|
74
|
-
|
|
75
|
-
act( () => {
|
|
76
|
-
onKeyDown( {
|
|
77
|
-
key: 'Enter',
|
|
78
|
-
stopPropagation: jest.fn(),
|
|
79
|
-
preventDefault: jest.fn(),
|
|
80
|
-
target: { innerText: newValue },
|
|
81
|
-
} as never );
|
|
82
|
-
} );
|
|
83
|
-
|
|
84
|
-
expect( onSubmit ).toHaveBeenCalledWith( newValue );
|
|
85
|
-
} );
|
|
86
|
-
|
|
87
|
-
it( 'should remove the editable content attribute on blur', () => {
|
|
88
|
-
// Arrange
|
|
89
|
-
const { result } = renderHook( () =>
|
|
90
|
-
useEditable( {
|
|
91
|
-
value: '',
|
|
92
|
-
onSubmit: jest.fn(),
|
|
93
|
-
} )
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
// Act.
|
|
97
|
-
act( result.current.openEditMode );
|
|
98
|
-
|
|
99
|
-
// Assert.
|
|
100
|
-
expect( result.current.isEditing ).toBe( true );
|
|
101
|
-
|
|
102
|
-
// Act.
|
|
103
|
-
act( result.current.getProps().onBlur );
|
|
104
|
-
|
|
105
|
-
// Assert.
|
|
106
|
-
expect( result.current.isEditing ).toBe( false );
|
|
107
|
-
} );
|
|
108
|
-
|
|
109
|
-
it( 'should set error message id validation fails', () => {
|
|
110
|
-
// Arrange.
|
|
111
|
-
const newValue = 'invalid-value';
|
|
112
|
-
const value = 'Some value';
|
|
113
|
-
const onSubmit = jest.fn();
|
|
114
|
-
|
|
115
|
-
const validation = ( v: string ) => {
|
|
116
|
-
if ( v === newValue ) {
|
|
117
|
-
return 'Nope';
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return null;
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
const { result } = renderHook( () =>
|
|
124
|
-
useEditable( {
|
|
125
|
-
value,
|
|
126
|
-
onSubmit,
|
|
127
|
-
validation,
|
|
128
|
-
} )
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
// Act.
|
|
132
|
-
act( result.current.openEditMode );
|
|
133
|
-
|
|
134
|
-
// Assert.
|
|
135
|
-
expect( result.current.error ).toBeNull();
|
|
136
|
-
|
|
137
|
-
// Act.
|
|
138
|
-
act( () => {
|
|
139
|
-
result.current.getProps().onInput( { target: { innerText: newValue } } as never );
|
|
140
|
-
} );
|
|
141
|
-
|
|
142
|
-
// Assert.
|
|
143
|
-
expect( result.current.error ).toBe( 'Nope' );
|
|
144
|
-
|
|
145
|
-
// Act.
|
|
146
|
-
act( () => {
|
|
147
|
-
result.current.getProps().onKeyDown( {
|
|
148
|
-
key: 'Enter',
|
|
149
|
-
stopPropagation: jest.fn(),
|
|
150
|
-
preventDefault: jest.fn(),
|
|
151
|
-
target: { innerText: newValue },
|
|
152
|
-
} as never );
|
|
153
|
-
} );
|
|
154
|
-
|
|
155
|
-
// Assert.
|
|
156
|
-
expect( onSubmit ).not.toHaveBeenCalled();
|
|
157
|
-
} );
|
|
158
|
-
|
|
159
|
-
it( 'should not run validation & submit if the value has not changed', () => {
|
|
160
|
-
// Arrange.
|
|
161
|
-
const value = 'initial value';
|
|
162
|
-
const onSubmit = jest.fn();
|
|
163
|
-
|
|
164
|
-
const validation = () => {
|
|
165
|
-
return 'test-error';
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
const { result } = renderHook( () =>
|
|
169
|
-
useEditable( {
|
|
170
|
-
value,
|
|
171
|
-
onSubmit,
|
|
172
|
-
validation,
|
|
173
|
-
} )
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
// Act.
|
|
177
|
-
act( result.current.openEditMode );
|
|
178
|
-
|
|
179
|
-
// Assert.
|
|
180
|
-
expect( result.current.error ).toBeNull();
|
|
181
|
-
|
|
182
|
-
// Act.
|
|
183
|
-
act( () => {
|
|
184
|
-
result.current.getProps().onInput( { target: { innerText: 'new value' } } as never );
|
|
185
|
-
} );
|
|
186
|
-
|
|
187
|
-
// Assert.
|
|
188
|
-
expect( result.current.error ).toBe( 'test-error' );
|
|
189
|
-
|
|
190
|
-
act( () => {
|
|
191
|
-
result.current.getProps().onInput( { target: { innerText: value } } as never );
|
|
192
|
-
} );
|
|
193
|
-
|
|
194
|
-
expect( result.current.error ).toBe( null );
|
|
195
|
-
|
|
196
|
-
// Act.
|
|
197
|
-
act( () => {
|
|
198
|
-
result.current.getProps().onKeyDown( {
|
|
199
|
-
key: 'Enter',
|
|
200
|
-
stopPropagation: jest.fn(),
|
|
201
|
-
preventDefault: jest.fn(),
|
|
202
|
-
target: { innerText: value },
|
|
203
|
-
} as never );
|
|
204
|
-
} );
|
|
205
|
-
|
|
206
|
-
// Assert.
|
|
207
|
-
expect( onSubmit ).not.toHaveBeenCalled();
|
|
208
|
-
} );
|
|
209
|
-
} );
|