@hero-design/rn-work-uikit 1.3.1 → 1.5.0
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/CHANGELOG.md +28 -0
- package/lib/index.js +19933 -735
- package/package.json +3 -2
- package/src/components/DatePicker/__tests__/__snapshots__/index.spec.tsx.snap +3 -3
- package/src/components/FormGroup/__tests__/__snapshots__/index.spec.tsx.snap +903 -0
- package/src/components/FormGroup/__tests__/index.spec.tsx +306 -0
- package/src/components/FormGroup/__tests__/utils.spec.ts +73 -0
- package/src/components/FormGroup/index.tsx +106 -0
- package/src/components/FormGroup/utils.ts +67 -0
- package/src/components/RichTextEditor/EditorEvent.ts +7 -0
- package/src/components/RichTextEditor/EditorToolbar.tsx +216 -0
- package/src/components/RichTextEditor/MentionList.tsx +99 -0
- package/src/components/RichTextEditor/RichTextEditor.tsx +88 -0
- package/src/components/RichTextEditor/RichTextEditorInput.tsx +292 -0
- package/src/components/RichTextEditor/StyledRichTextEditor.tsx +15 -0
- package/src/components/RichTextEditor/StyledToolbar.ts +32 -0
- package/src/components/RichTextEditor/__mocks__/hero-editor.js +3 -0
- package/src/components/RichTextEditor/__mocks__/heroEditorApp.ts +2 -0
- package/src/components/RichTextEditor/__tests__/EditorToolbar.spec.tsx +144 -0
- package/src/components/RichTextEditor/__tests__/MentionList.spec.tsx +105 -0
- package/src/components/RichTextEditor/__tests__/RichTextEditorInput.spec.tsx +136 -0
- package/src/components/RichTextEditor/__tests__/__snapshots__/EditorToolbar.spec.tsx.snap +414 -0
- package/src/components/RichTextEditor/__tests__/__snapshots__/MentionList.spec.tsx.snap +13 -0
- package/src/components/RichTextEditor/constants.ts +9 -0
- package/src/{hero-editor.d.ts → components/RichTextEditor/hero-editor.d.ts} +6 -0
- package/src/components/RichTextEditor/heroEditorApp.ts +3 -0
- package/src/components/RichTextEditor/index.tsx +20 -0
- package/src/components/RichTextEditor/types.ts +87 -0
- package/src/components/RichTextEditor/utils/events.ts +31 -0
- package/src/components/RichTextEditor/utils/rnWebView.tsx +30 -0
- package/src/components/Select/__tests__/__snapshots__/index.spec.tsx.snap +24 -2
- package/src/components/Select/index.tsx +11 -10
- package/src/components/TextInput/Group/__tests__/__snapshots__/index.spec.tsx.snap +3 -3
- package/src/components/TextInput/Group/index.tsx +6 -1
- package/src/components/TextInput/InputComponent.tsx +59 -18
- package/src/components/TextInput/InputRow.tsx +13 -7
- package/src/components/TextInput/StyledTextInput.tsx +3 -3
- package/src/components/TextInput/__tests__/__snapshots__/index.spec.tsx.snap +17 -17
- package/src/components/TextInput/index.tsx +22 -13
- package/src/components/TextInput/types.ts +30 -5
- package/src/index.ts +3 -1
- package/src/utils/hooks.ts +10 -0
- package/stats/1.5.0/rn-work-uikit-stats.html +4844 -0
- package/stats/1.3.1/rn-work-uikit-stats.html +0 -4844
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { styled } from '@hero-design/rn';
|
|
2
|
+
import { StyleSheet, TouchableOpacity, View } from 'react-native';
|
|
3
|
+
|
|
4
|
+
export const StyledToolbarButton = styled(TouchableOpacity)<{
|
|
5
|
+
selected: boolean;
|
|
6
|
+
}>(({ theme, selected }) => ({
|
|
7
|
+
width: theme.__hd__.richTextEditor.sizes.toolbarButtonSize,
|
|
8
|
+
height: theme.__hd__.richTextEditor.sizes.toolbarButtonSize,
|
|
9
|
+
alignItems: 'center',
|
|
10
|
+
justifyContent: 'center',
|
|
11
|
+
backgroundColor: selected
|
|
12
|
+
? theme.__hd__.richTextEditor.colors.toolbarButtonSelectedBackground
|
|
13
|
+
: undefined,
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
export const StyledToolbar = styled(View)(({ theme }) => ({
|
|
17
|
+
flexDirection: 'row',
|
|
18
|
+
alignItems: 'center',
|
|
19
|
+
borderTopWidth: StyleSheet.hairlineWidth,
|
|
20
|
+
borderTopColor: theme.__hd__.richTextEditor.colors.toolbarBorderColor,
|
|
21
|
+
backgroundColor: theme.__hd__.richTextEditor.colors.toolbarBackgroundColor,
|
|
22
|
+
paddingHorizontal: theme.__hd__.richTextEditor.space.toolbarHorizontalPadding,
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
export const StyledSeparator = styled(View)(({ theme }) => ({
|
|
26
|
+
width: theme.__hd__.richTextEditor.sizes.toolbarSeparatorWidth,
|
|
27
|
+
height: theme.__hd__.richTextEditor.sizes.toolbarSeparatorHeight,
|
|
28
|
+
flexDirection: 'row',
|
|
29
|
+
alignItems: 'center',
|
|
30
|
+
marginHorizontal: theme.space.small,
|
|
31
|
+
backgroundColor: theme.colors.secondaryOutline,
|
|
32
|
+
}));
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { act, fireEvent, waitFor } from '@testing-library/react-native';
|
|
3
|
+
import type { RenderAPI } from '@testing-library/react-native';
|
|
4
|
+
import EditorToolbar from '../EditorToolbar';
|
|
5
|
+
import { emitter as editorEventEmmitor } from '../EditorEvent';
|
|
6
|
+
import { theme, ThemeProvider } from '../../../index';
|
|
7
|
+
import * as Events from '../utils/events';
|
|
8
|
+
import renderWithTheme from '../../../../testUtils/renderWithTheme';
|
|
9
|
+
|
|
10
|
+
describe('EditorToolbar', () => {
|
|
11
|
+
it('should not render toolbar when the editor is not focused', () => {
|
|
12
|
+
const wrapper = renderWithTheme(
|
|
13
|
+
<EditorToolbar testID="editor-toolbar" name="toolbar" />
|
|
14
|
+
);
|
|
15
|
+
const toolbar = wrapper.queryByTestId('editor-toolbar');
|
|
16
|
+
expect(toolbar).toBeNull();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe('when the editor is focused', () => {
|
|
20
|
+
let wrapper: RenderAPI;
|
|
21
|
+
|
|
22
|
+
beforeEach(async () => {
|
|
23
|
+
wrapper = renderWithTheme(
|
|
24
|
+
<EditorToolbar name="toolbar" testID="toolbar" />
|
|
25
|
+
);
|
|
26
|
+
act(() => {
|
|
27
|
+
editorEventEmmitor.emit('toolbar/editor-focus');
|
|
28
|
+
});
|
|
29
|
+
await waitFor(() => wrapper.getByTestId('toolbar'));
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should render toolbar', async () => {
|
|
33
|
+
expect(wrapper.toJSON()).toMatchSnapshot();
|
|
34
|
+
|
|
35
|
+
[
|
|
36
|
+
'format-bold',
|
|
37
|
+
'format-italic',
|
|
38
|
+
'format-underlined',
|
|
39
|
+
'format-list-bulleted',
|
|
40
|
+
'format-list-numbered',
|
|
41
|
+
'format-heading1',
|
|
42
|
+
'format-heading2',
|
|
43
|
+
].forEach((testId) => {
|
|
44
|
+
expect(wrapper.queryAllByTestId(testId)).toHaveLength(1);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should hide toolbar when blur', async () => {
|
|
49
|
+
act(() => {
|
|
50
|
+
editorEventEmmitor.emit('toolbar/editor-blur');
|
|
51
|
+
});
|
|
52
|
+
await waitFor(() => wrapper.queryAllByTestId('toolbar').length === 0);
|
|
53
|
+
expect(wrapper.queryAllByTestId('toolbar')).toHaveLength(0);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe("should change button's background color when pressing", () => {
|
|
57
|
+
it('should send event and highlight buttons correctly', async () => {
|
|
58
|
+
const emmitedEvents: string[] = [];
|
|
59
|
+
|
|
60
|
+
const eventNameAndTestIDArray = [
|
|
61
|
+
{
|
|
62
|
+
eventName: 'toolbar/bold',
|
|
63
|
+
testID: 'format-bold',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
eventName: 'toolbar/italic',
|
|
67
|
+
testID: 'format-italic',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
eventName: 'toolbar/underline',
|
|
71
|
+
testID: 'format-underlined',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
eventName: 'toolbar/bulleted-list',
|
|
75
|
+
testID: 'format-list-bulleted',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
eventName: 'toolbar/numbered-list',
|
|
79
|
+
testID: 'format-list-numbered',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
eventName: 'toolbar/heading-one',
|
|
83
|
+
testID: 'format-heading1',
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
eventName: 'toolbar/heading-two',
|
|
87
|
+
testID: 'format-heading2',
|
|
88
|
+
},
|
|
89
|
+
];
|
|
90
|
+
|
|
91
|
+
eventNameAndTestIDArray.forEach(async ({ eventName, testID }) => {
|
|
92
|
+
Events.on(editorEventEmmitor, eventName, () => {
|
|
93
|
+
emmitedEvents.push(testID);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
expect(wrapper.getByTestId(testID)).toHaveStyle({
|
|
97
|
+
backgroundColor: undefined,
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
await act(() => {
|
|
101
|
+
fireEvent.press(wrapper.getByTestId(testID));
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// rerender
|
|
105
|
+
wrapper.rerender(
|
|
106
|
+
<ThemeProvider theme={theme}>
|
|
107
|
+
<EditorToolbar name="toolbar" testID="toolbar" />
|
|
108
|
+
</ThemeProvider>
|
|
109
|
+
);
|
|
110
|
+
// match snapshot
|
|
111
|
+
// add waitfor to ensure the style is applied
|
|
112
|
+
await waitFor(() => {
|
|
113
|
+
expect(wrapper.getByTestId(testID)).toHaveStyle({
|
|
114
|
+
backgroundColor:
|
|
115
|
+
theme.__hd__.richTextEditor.colors
|
|
116
|
+
.toolbarButtonSelectedBackground,
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const standaloneButtonTestIDs = [
|
|
122
|
+
'format-list-bulleted',
|
|
123
|
+
'format-list-numbered',
|
|
124
|
+
'format-heading1',
|
|
125
|
+
];
|
|
126
|
+
standaloneButtonTestIDs.forEach((testID) => {
|
|
127
|
+
expect(wrapper.getByTestId(testID)).toHaveStyle({
|
|
128
|
+
backgroundColor: undefined,
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
expect(emmitedEvents).toMatchObject([
|
|
133
|
+
'format-bold',
|
|
134
|
+
'format-italic',
|
|
135
|
+
'format-underlined',
|
|
136
|
+
'format-list-bulleted',
|
|
137
|
+
'format-list-numbered',
|
|
138
|
+
'format-heading1',
|
|
139
|
+
'format-heading2',
|
|
140
|
+
]);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
});
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import type { RenderAPI } from '@testing-library/react-native';
|
|
2
|
+
import { act, fireEvent, render } from '@testing-library/react-native';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { Text, View } from 'react-native';
|
|
5
|
+
import { emitter as editorEventEmitter } from '../EditorEvent';
|
|
6
|
+
import MentionList from '../MentionList';
|
|
7
|
+
import * as Events from '../utils/events';
|
|
8
|
+
import renderWithTheme from '../../../../testUtils/renderWithTheme';
|
|
9
|
+
|
|
10
|
+
const SuggestionListData: Array<{ id: string; name: string }> = [
|
|
11
|
+
{ id: '1', name: 'Kien Tran' },
|
|
12
|
+
{ id: '2', name: 'Minh Dinh' },
|
|
13
|
+
{ id: '3', name: 'Hieu Pham' },
|
|
14
|
+
{ id: '4', name: 'Hau' },
|
|
15
|
+
{ id: '5', name: 'Tung Ten' },
|
|
16
|
+
{ id: '6', name: 'Thong Quach' },
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const SuggestionList = ({
|
|
20
|
+
searchValue,
|
|
21
|
+
onSelect,
|
|
22
|
+
}: {
|
|
23
|
+
searchValue: string;
|
|
24
|
+
onSelect: (id: string, name: string) => void;
|
|
25
|
+
}) => {
|
|
26
|
+
const filteredData = SuggestionListData.filter((item) =>
|
|
27
|
+
item.name.includes(searchValue)
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<View>
|
|
32
|
+
{filteredData.map((item) => (
|
|
33
|
+
<Text key={item.id} onPress={() => onSelect(item.id, item.name)}>
|
|
34
|
+
{item.name}
|
|
35
|
+
</Text>
|
|
36
|
+
))}
|
|
37
|
+
</View>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
describe('MentionList', () => {
|
|
42
|
+
describe('when search string is empty', () => {
|
|
43
|
+
it('should not render mention list', () => {
|
|
44
|
+
const wrapper = render(
|
|
45
|
+
<MentionList
|
|
46
|
+
name="give-shout-out"
|
|
47
|
+
render={() => <Text>Mention List</Text>}
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
expect(wrapper.toJSON()).toBeNull();
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
describe('when search string is not empty', () => {
|
|
56
|
+
let wrapper: RenderAPI;
|
|
57
|
+
|
|
58
|
+
beforeEach(async () => {
|
|
59
|
+
wrapper = renderWithTheme(
|
|
60
|
+
<MentionList
|
|
61
|
+
name="give-shout-out"
|
|
62
|
+
render={(
|
|
63
|
+
searchValue: string,
|
|
64
|
+
onSelect: (id: string, name: string) => void
|
|
65
|
+
) => <SuggestionList searchValue={searchValue} onSelect={onSelect} />}
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
await act(() => {
|
|
69
|
+
editorEventEmitter.emit('give-shout-out/mention-search', {
|
|
70
|
+
search: 'Hieu',
|
|
71
|
+
target: 'give-shout-out',
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should render mention list showing filtered results', async () => {
|
|
77
|
+
expect(wrapper.toJSON()).toMatchSnapshot();
|
|
78
|
+
expect(wrapper.queryAllByText('Hieu Pham')).toHaveLength(1);
|
|
79
|
+
expect(wrapper.queryAllByText('Kien Tran')).toHaveLength(0);
|
|
80
|
+
expect(wrapper.queryAllByText('Minh Dinh')).toHaveLength(0);
|
|
81
|
+
expect(wrapper.queryAllByText('Hau')).toHaveLength(0);
|
|
82
|
+
expect(wrapper.queryAllByText('Tung Teng')).toHaveLength(0);
|
|
83
|
+
expect(wrapper.queryAllByText('Thong Quach')).toHaveLength(0);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe('onPress suggesstion item', () => {
|
|
87
|
+
it('should emit action metion-only', () => {
|
|
88
|
+
const result: { id: string; name: string; target: string }[] = [];
|
|
89
|
+
act(() => {
|
|
90
|
+
Events.on(
|
|
91
|
+
editorEventEmitter,
|
|
92
|
+
'give-shout-out/mention-apply',
|
|
93
|
+
(data: { id: string; name: string; target: string }) => {
|
|
94
|
+
result.push(data);
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
fireEvent(wrapper.getByText('Hieu Pham'), 'press');
|
|
99
|
+
expect(result).toMatchObject([
|
|
100
|
+
{ id: '3', name: 'Hieu Pham', target: 'give-shout-out' },
|
|
101
|
+
]);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
});
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { fireEvent } from '@testing-library/react-native';
|
|
3
|
+
import RichTextEditorInput from '../RichTextEditorInput';
|
|
4
|
+
import { emitter } from '../EditorEvent';
|
|
5
|
+
import * as Events from '../utils/events';
|
|
6
|
+
import renderWithTheme from '../../../../testUtils/renderWithTheme';
|
|
7
|
+
|
|
8
|
+
// Mock minimal EditorValue type for test
|
|
9
|
+
const initialValue = [
|
|
10
|
+
{ type: 'paragraph', children: [{ text: 'Hello world' }] },
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
describe('RichTextEditorInput', () => {
|
|
14
|
+
it('renders a WebView with correct initial html', () => {
|
|
15
|
+
const { getByTestId } = renderWithTheme(
|
|
16
|
+
<RichTextEditorInput
|
|
17
|
+
value={initialValue}
|
|
18
|
+
name="test-editor"
|
|
19
|
+
autoFocus={false}
|
|
20
|
+
placeholder="Type something..."
|
|
21
|
+
onChange={jest.fn()}
|
|
22
|
+
/>
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
const webview = getByTestId('webview');
|
|
26
|
+
expect(webview).toBeTruthy();
|
|
27
|
+
expect(webview.props.source.html).toContain(
|
|
28
|
+
'placeholder: "Type something..."'
|
|
29
|
+
);
|
|
30
|
+
expect(webview.props.source.html).toContain(JSON.stringify(initialValue));
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('handles editor-change event from webview', () => {
|
|
34
|
+
const onChange = jest.fn();
|
|
35
|
+
const { getByTestId } = renderWithTheme(
|
|
36
|
+
<RichTextEditorInput
|
|
37
|
+
value={initialValue}
|
|
38
|
+
name="test-editor"
|
|
39
|
+
autoFocus={false}
|
|
40
|
+
placeholder="Type here..."
|
|
41
|
+
onChange={onChange}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const webview = getByTestId('webview');
|
|
46
|
+
const newValue = [{ type: 'paragraph', children: [{ text: 'Changed' }] }];
|
|
47
|
+
fireEvent(webview, 'message', {
|
|
48
|
+
nativeEvent: {
|
|
49
|
+
data: JSON.stringify({
|
|
50
|
+
type: '@hero-editor/webview/editor-change',
|
|
51
|
+
data: { value: newValue },
|
|
52
|
+
}),
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
expect(onChange).toHaveBeenCalledWith(newValue);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('handles editor-focus and editor-blur events from webview', () => {
|
|
60
|
+
const onFocus = jest.fn();
|
|
61
|
+
const onBlur = jest.fn();
|
|
62
|
+
const { getByTestId } = renderWithTheme(
|
|
63
|
+
<RichTextEditorInput
|
|
64
|
+
value={initialValue}
|
|
65
|
+
name="test-editor"
|
|
66
|
+
autoFocus={false}
|
|
67
|
+
placeholder="Type here..."
|
|
68
|
+
onChange={jest.fn()}
|
|
69
|
+
onFocus={onFocus}
|
|
70
|
+
onBlur={onBlur}
|
|
71
|
+
/>
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const webview = getByTestId('webview');
|
|
75
|
+
|
|
76
|
+
// Spy on emitter
|
|
77
|
+
const spy = jest.spyOn(Events, 'emit');
|
|
78
|
+
|
|
79
|
+
// Simulate focus
|
|
80
|
+
fireEvent(webview, 'message', {
|
|
81
|
+
nativeEvent: {
|
|
82
|
+
data: JSON.stringify({
|
|
83
|
+
type: '@hero-editor/webview/editor-focus',
|
|
84
|
+
}),
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
expect(spy).toHaveBeenCalledWith(
|
|
88
|
+
emitter,
|
|
89
|
+
'test-editor/editor-focus',
|
|
90
|
+
undefined
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
// Simulate blur
|
|
94
|
+
fireEvent(webview, 'message', {
|
|
95
|
+
nativeEvent: {
|
|
96
|
+
data: JSON.stringify({
|
|
97
|
+
type: '@hero-editor/webview/editor-blur',
|
|
98
|
+
}),
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
expect(spy).toHaveBeenCalledWith(
|
|
102
|
+
emitter,
|
|
103
|
+
'test-editor/editor-blur',
|
|
104
|
+
undefined
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
spy.mockRestore();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('handles cursor-change event from webview', () => {
|
|
111
|
+
const onCursorChange = jest.fn();
|
|
112
|
+
const { getByTestId } = renderWithTheme(
|
|
113
|
+
<RichTextEditorInput
|
|
114
|
+
value={initialValue}
|
|
115
|
+
name="test-editor"
|
|
116
|
+
autoFocus={false}
|
|
117
|
+
placeholder="Type here..."
|
|
118
|
+
onChange={jest.fn()}
|
|
119
|
+
onCursorChange={onCursorChange}
|
|
120
|
+
/>
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
const webview = getByTestId('webview');
|
|
124
|
+
const cursorData = { position: { top: 10 } };
|
|
125
|
+
fireEvent(webview, 'message', {
|
|
126
|
+
nativeEvent: {
|
|
127
|
+
data: JSON.stringify({
|
|
128
|
+
type: '@hero-editor/webview/cursor-change',
|
|
129
|
+
data: cursorData,
|
|
130
|
+
}),
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
expect(onCursorChange).toHaveBeenCalledWith(cursorData);
|
|
135
|
+
});
|
|
136
|
+
});
|