@elementor/editor-v1-adapters 0.1.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/LICENSE +674 -0
- package/README.md +5 -0
- package/dist/index.d.ts +81 -0
- package/dist/index.js +334 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +288 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +38 -0
- package/src/__tests__/utils.ts +39 -0
- package/src/dispatchers/__tests__/index.test.ts +126 -0
- package/src/dispatchers/dispatchers.ts +38 -0
- package/src/dispatchers/index.ts +1 -0
- package/src/dispatchers/types.ts +10 -0
- package/src/dispatchers/utils.ts +18 -0
- package/src/hooks/__tests__/test-utils.ts +21 -0
- package/src/hooks/__tests__/use-is-preview-mode.test.ts +47 -0
- package/src/hooks/__tests__/use-is-route-active.test.ts +93 -0
- package/src/hooks/__tests__/use-route-status.test.ts +124 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/use-is-preview-mode.ts +10 -0
- package/src/hooks/use-is-route-active.ts +14 -0
- package/src/hooks/use-listen-to.ts +21 -0
- package/src/hooks/use-route-status.ts +32 -0
- package/src/index.ts +4 -0
- package/src/listeners/__tests__/index.test.ts +343 -0
- package/src/listeners/event-creators.ts +48 -0
- package/src/listeners/index.ts +5 -0
- package/src/listeners/is-ready.ts +14 -0
- package/src/listeners/listeners.ts +124 -0
- package/src/listeners/types.ts +45 -0
- package/src/listeners/utils.ts +44 -0
- package/src/readers/__tests__/index.test.ts +71 -0
- package/src/readers/index.ts +13 -0
- package/src/readers/types.ts +16 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { act, renderHook } from '@testing-library/react-hooks';
|
|
2
|
+
import useIsRouteActive from '../use-is-route-active';
|
|
3
|
+
import { dispatchRouteClose, dispatchRouteOpen } from '../../__tests__/utils';
|
|
4
|
+
import { mockIsRouteActive } from './test-utils';
|
|
5
|
+
|
|
6
|
+
describe( '@elementor/editor-v1-adapters - useIsRouteActive', () => {
|
|
7
|
+
it( 'should return false when a route is inactive by default', () => {
|
|
8
|
+
// Arrange.
|
|
9
|
+
const route = 'panel/menu';
|
|
10
|
+
|
|
11
|
+
mockIsRouteActive( () => false );
|
|
12
|
+
|
|
13
|
+
// Act.
|
|
14
|
+
const { result } = renderHook( () => useIsRouteActive( route ) );
|
|
15
|
+
|
|
16
|
+
// Assert.
|
|
17
|
+
expect( result.current ).toBe( false );
|
|
18
|
+
} );
|
|
19
|
+
|
|
20
|
+
it( 'should return true when a route is active by default', () => {
|
|
21
|
+
// Arrange.
|
|
22
|
+
const route = 'panel/menu';
|
|
23
|
+
|
|
24
|
+
mockIsRouteActive( () => true );
|
|
25
|
+
|
|
26
|
+
// Act.
|
|
27
|
+
const { result } = renderHook( () => useIsRouteActive( route ) );
|
|
28
|
+
|
|
29
|
+
// Assert.
|
|
30
|
+
expect( result.current ).toBe( true );
|
|
31
|
+
} );
|
|
32
|
+
|
|
33
|
+
it( 'should return true when a route gets activated', () => {
|
|
34
|
+
// Arrange.
|
|
35
|
+
const route = 'panel/menu';
|
|
36
|
+
|
|
37
|
+
mockIsRouteActive( () => false );
|
|
38
|
+
|
|
39
|
+
// Act.
|
|
40
|
+
const { result } = renderHook( () => useIsRouteActive( route ) );
|
|
41
|
+
|
|
42
|
+
act( () => {
|
|
43
|
+
mockIsRouteActive( () => true );
|
|
44
|
+
dispatchRouteOpen( route );
|
|
45
|
+
} );
|
|
46
|
+
|
|
47
|
+
// Assert.
|
|
48
|
+
expect( result.current ).toBe( true );
|
|
49
|
+
} );
|
|
50
|
+
|
|
51
|
+
it( 'should return false when a route gets deactivated', () => {
|
|
52
|
+
// Arrange.
|
|
53
|
+
const route = 'panel/menu';
|
|
54
|
+
|
|
55
|
+
mockIsRouteActive( () => true );
|
|
56
|
+
|
|
57
|
+
// Act.
|
|
58
|
+
const { result } = renderHook( () => useIsRouteActive( route ) );
|
|
59
|
+
|
|
60
|
+
act( () => {
|
|
61
|
+
mockIsRouteActive( () => false );
|
|
62
|
+
dispatchRouteClose( route );
|
|
63
|
+
} );
|
|
64
|
+
|
|
65
|
+
// Assert.
|
|
66
|
+
expect( result.current ).toBe( false );
|
|
67
|
+
} );
|
|
68
|
+
|
|
69
|
+
it( 'should re-check whether the route is active when changing it', () => {
|
|
70
|
+
// Arrange.
|
|
71
|
+
mockIsRouteActive( ( r ) => {
|
|
72
|
+
return 'active/route' === r;
|
|
73
|
+
} );
|
|
74
|
+
|
|
75
|
+
// Act.
|
|
76
|
+
const { result, rerender } = renderHook( ( { route } ) => useIsRouteActive( route ), {
|
|
77
|
+
initialProps: {
|
|
78
|
+
route: 'active/route',
|
|
79
|
+
},
|
|
80
|
+
} );
|
|
81
|
+
|
|
82
|
+
// Assert.
|
|
83
|
+
expect( result.current ).toBe( true );
|
|
84
|
+
|
|
85
|
+
// Act.
|
|
86
|
+
rerender( {
|
|
87
|
+
route: 'inactive/route',
|
|
88
|
+
} );
|
|
89
|
+
|
|
90
|
+
// Assert.
|
|
91
|
+
expect( result.current ).toBe( false );
|
|
92
|
+
} );
|
|
93
|
+
} );
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { renderHook } from '@testing-library/react-hooks';
|
|
2
|
+
import useRouteStatus from '../use-route-status';
|
|
3
|
+
import { mockGetCurrentEditMode, mockIsRouteActive } from './test-utils';
|
|
4
|
+
|
|
5
|
+
describe( '@elementor/editor-v1-adapters - useRouteStatus', () => {
|
|
6
|
+
it.each( [
|
|
7
|
+
{
|
|
8
|
+
input: {
|
|
9
|
+
isRouteActive: true,
|
|
10
|
+
isKitRouteActive: false,
|
|
11
|
+
isPreviewMode: false,
|
|
12
|
+
options: {},
|
|
13
|
+
},
|
|
14
|
+
expected: true,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
input: {
|
|
18
|
+
isRouteActive: true,
|
|
19
|
+
isKitRouteActive: false,
|
|
20
|
+
isPreviewMode: true,
|
|
21
|
+
options: {
|
|
22
|
+
blockOnPreviewMode: false,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
expected: true,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
input: {
|
|
29
|
+
isRouteActive: false,
|
|
30
|
+
isKitRouteActive: false,
|
|
31
|
+
isPreviewMode: false,
|
|
32
|
+
options: {},
|
|
33
|
+
},
|
|
34
|
+
expected: false,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
input: {
|
|
38
|
+
isRouteActive: true,
|
|
39
|
+
isKitRouteActive: false,
|
|
40
|
+
isPreviewMode: true,
|
|
41
|
+
options: {},
|
|
42
|
+
},
|
|
43
|
+
expected: false,
|
|
44
|
+
},
|
|
45
|
+
] )( 'should check if the route is active: isRouteActive = $input.isRouteActive, isPreviewMode = $input.isPreviewMode, options: $input.options', ( {
|
|
46
|
+
input: { isRouteActive, isKitRouteActive, isPreviewMode, options },
|
|
47
|
+
expected,
|
|
48
|
+
} ) => {
|
|
49
|
+
// Arrange
|
|
50
|
+
mockIsRouteActive( ( route ) => route === 'panel/global' ? isKitRouteActive : isRouteActive );
|
|
51
|
+
mockGetCurrentEditMode( () => isPreviewMode ? 'preview' : 'edit' );
|
|
52
|
+
|
|
53
|
+
// Act.
|
|
54
|
+
const { result } = renderHook( () => useRouteStatus( 'panel/page-settings', options ) );
|
|
55
|
+
|
|
56
|
+
// Assert.
|
|
57
|
+
expect( result.current.isActive ).toBe( expected );
|
|
58
|
+
} );
|
|
59
|
+
|
|
60
|
+
it.each( [
|
|
61
|
+
{
|
|
62
|
+
input: {
|
|
63
|
+
isRouteActive: false,
|
|
64
|
+
isKitRouteActive: false,
|
|
65
|
+
isPreviewMode: false,
|
|
66
|
+
options: {},
|
|
67
|
+
},
|
|
68
|
+
expected: false,
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
input: {
|
|
72
|
+
isRouteActive: false,
|
|
73
|
+
isKitRouteActive: false,
|
|
74
|
+
isPreviewMode: true,
|
|
75
|
+
options: {
|
|
76
|
+
blockOnPreviewMode: false,
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
expected: false,
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
input: {
|
|
83
|
+
isRouteActive: false,
|
|
84
|
+
isKitRouteActive: true,
|
|
85
|
+
isPreviewMode: false,
|
|
86
|
+
options: {
|
|
87
|
+
blockOnKitRoutes: false,
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
expected: false,
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
input: {
|
|
94
|
+
isRouteActive: false,
|
|
95
|
+
isKitRouteActive: true,
|
|
96
|
+
isPreviewMode: false,
|
|
97
|
+
options: {},
|
|
98
|
+
},
|
|
99
|
+
expected: true,
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
input: {
|
|
103
|
+
isRouteActive: false,
|
|
104
|
+
isKitRouteActive: false,
|
|
105
|
+
isPreviewMode: true,
|
|
106
|
+
options: {},
|
|
107
|
+
},
|
|
108
|
+
expected: true,
|
|
109
|
+
},
|
|
110
|
+
] )( 'should check if the route is blocked: isKitRouteActive = $input.isKitRouteActive, isPreviewMode = $input.isPreviewMode, options: $input.options', ( {
|
|
111
|
+
input: { isRouteActive, isKitRouteActive, isPreviewMode, options },
|
|
112
|
+
expected,
|
|
113
|
+
} ) => {
|
|
114
|
+
// Arrange
|
|
115
|
+
mockIsRouteActive( ( route ) => route === 'panel/global' ? isKitRouteActive : isRouteActive );
|
|
116
|
+
mockGetCurrentEditMode( () => isPreviewMode ? 'preview' : 'edit' );
|
|
117
|
+
|
|
118
|
+
// Act.
|
|
119
|
+
const { result } = renderHook( () => useRouteStatus( 'panel/page-settings', options ) );
|
|
120
|
+
|
|
121
|
+
// Assert.
|
|
122
|
+
expect( result.current.isBlocked ).toBe( expected );
|
|
123
|
+
} );
|
|
124
|
+
} );
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import useListenTo from './use-listen-to';
|
|
2
|
+
import { getCurrentEditMode } from '../readers';
|
|
3
|
+
import { editModeChangeEvent } from '../listeners';
|
|
4
|
+
|
|
5
|
+
export default function useIsPreviewMode() {
|
|
6
|
+
return useListenTo(
|
|
7
|
+
editModeChangeEvent(),
|
|
8
|
+
() => getCurrentEditMode() === 'preview'
|
|
9
|
+
);
|
|
10
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import useListenTo from './use-listen-to';
|
|
2
|
+
import { isRouteActive } from '../readers';
|
|
3
|
+
import { routeCloseEvent, routeOpenEvent, RouteEventDescriptor } from '../listeners';
|
|
4
|
+
|
|
5
|
+
export default function useIsRouteActive( route: RouteEventDescriptor['name'] ) {
|
|
6
|
+
return useListenTo(
|
|
7
|
+
[
|
|
8
|
+
routeOpenEvent( route ),
|
|
9
|
+
routeCloseEvent( route ),
|
|
10
|
+
],
|
|
11
|
+
() => isRouteActive( route ),
|
|
12
|
+
[ route ]
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { EventDescriptor, listenTo } from '../listeners';
|
|
3
|
+
|
|
4
|
+
export default function useListenTo<T>(
|
|
5
|
+
event: EventDescriptor | EventDescriptor[],
|
|
6
|
+
getSnapshot: () => T,
|
|
7
|
+
deps: unknown[] = []
|
|
8
|
+
) {
|
|
9
|
+
const [ snapshot, setSnapshot ] = useState( () => getSnapshot() );
|
|
10
|
+
|
|
11
|
+
useEffect( () => {
|
|
12
|
+
const updateState = () => setSnapshot( getSnapshot() );
|
|
13
|
+
|
|
14
|
+
// Ensure the state is re-calculated when the dependencies have been changed.
|
|
15
|
+
updateState();
|
|
16
|
+
|
|
17
|
+
return listenTo( event, updateState );
|
|
18
|
+
}, deps ); // eslint-disable-line react-hooks/exhaustive-deps
|
|
19
|
+
|
|
20
|
+
return snapshot;
|
|
21
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import useIsPreviewMode from './use-is-preview-mode';
|
|
2
|
+
import useIsRouteActive from './use-is-route-active';
|
|
3
|
+
import { RouteEventDescriptor } from '../listeners';
|
|
4
|
+
|
|
5
|
+
type Options = {
|
|
6
|
+
blockOnKitRoutes?: boolean,
|
|
7
|
+
blockOnPreviewMode?: boolean,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default function useRouteStatus(
|
|
11
|
+
route: RouteEventDescriptor['name'],
|
|
12
|
+
{
|
|
13
|
+
blockOnKitRoutes = true,
|
|
14
|
+
blockOnPreviewMode = true,
|
|
15
|
+
}: Options = {}
|
|
16
|
+
) {
|
|
17
|
+
const isRouteActive = useIsRouteActive( route );
|
|
18
|
+
const isKitRouteActive = useIsRouteActive( 'panel/global' );
|
|
19
|
+
const isPreviewMode = useIsPreviewMode();
|
|
20
|
+
|
|
21
|
+
const isActive = isRouteActive && ! ( blockOnPreviewMode && isPreviewMode );
|
|
22
|
+
|
|
23
|
+
const isBlocked = (
|
|
24
|
+
( blockOnPreviewMode && isPreviewMode ) ||
|
|
25
|
+
( blockOnKitRoutes && isKitRouteActive )
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
isActive,
|
|
30
|
+
isBlocked,
|
|
31
|
+
};
|
|
32
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import {
|
|
2
|
+
commandEndEvent,
|
|
3
|
+
commandStartEvent,
|
|
4
|
+
dispatchReadyEvent,
|
|
5
|
+
listenTo,
|
|
6
|
+
routeOpenEvent,
|
|
7
|
+
routeCloseEvent,
|
|
8
|
+
windowEvent,
|
|
9
|
+
v1ReadyEvent,
|
|
10
|
+
setReady,
|
|
11
|
+
ExtendedWindow,
|
|
12
|
+
} from '../';
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
dispatchCommandAfter,
|
|
16
|
+
dispatchCommandBefore,
|
|
17
|
+
dispatchRouteClose,
|
|
18
|
+
dispatchRouteOpen,
|
|
19
|
+
dispatchWindowEvent,
|
|
20
|
+
} from '../../__tests__/utils';
|
|
21
|
+
|
|
22
|
+
describe( '@elementor/editor-v1-adapters/listeners', () => {
|
|
23
|
+
beforeEach( () => {
|
|
24
|
+
jest.useFakeTimers();
|
|
25
|
+
} );
|
|
26
|
+
|
|
27
|
+
afterEach( () => {
|
|
28
|
+
jest.useRealTimers();
|
|
29
|
+
} );
|
|
30
|
+
|
|
31
|
+
it( 'should listen to command start', () => {
|
|
32
|
+
// Arrange.
|
|
33
|
+
const commandToListen = 'editor/documents/open',
|
|
34
|
+
anotherCommand = 'non/related/command',
|
|
35
|
+
callback = jest.fn();
|
|
36
|
+
|
|
37
|
+
// Act.
|
|
38
|
+
listenTo(
|
|
39
|
+
commandStartEvent( commandToListen ),
|
|
40
|
+
callback
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
// Dispatch the command to test.
|
|
44
|
+
dispatchCommandBefore( commandToListen );
|
|
45
|
+
dispatchCommandAfter( commandToListen );
|
|
46
|
+
|
|
47
|
+
// Dispatch another command to make sure we don't listen to it.
|
|
48
|
+
dispatchCommandBefore( anotherCommand );
|
|
49
|
+
dispatchCommandAfter( anotherCommand );
|
|
50
|
+
|
|
51
|
+
// Assert.
|
|
52
|
+
expect( callback ).toHaveBeenCalledTimes( 1 );
|
|
53
|
+
expect( callback ).toHaveBeenCalledWith( {
|
|
54
|
+
type: 'command',
|
|
55
|
+
command: 'editor/documents/open',
|
|
56
|
+
originalEvent: expect.any( CustomEvent ),
|
|
57
|
+
} );
|
|
58
|
+
} );
|
|
59
|
+
|
|
60
|
+
it( 'should listen to command end', () => {
|
|
61
|
+
// Arrange.
|
|
62
|
+
const commandToListen = 'editor/documents/open',
|
|
63
|
+
anotherCommand = 'non/related/command',
|
|
64
|
+
callback = jest.fn();
|
|
65
|
+
|
|
66
|
+
// Act.
|
|
67
|
+
listenTo(
|
|
68
|
+
commandEndEvent( commandToListen ),
|
|
69
|
+
callback
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
// Dispatch the command to test.
|
|
73
|
+
dispatchCommandBefore( commandToListen );
|
|
74
|
+
dispatchCommandAfter( commandToListen );
|
|
75
|
+
|
|
76
|
+
// Dispatch another command to make sure we don't listen to it.
|
|
77
|
+
dispatchCommandBefore( anotherCommand );
|
|
78
|
+
dispatchCommandAfter( anotherCommand );
|
|
79
|
+
|
|
80
|
+
// Assert.
|
|
81
|
+
expect( callback ).toHaveBeenCalledTimes( 1 );
|
|
82
|
+
expect( callback ).toHaveBeenCalledWith( {
|
|
83
|
+
type: 'command',
|
|
84
|
+
command: 'editor/documents/open',
|
|
85
|
+
originalEvent: expect.any( CustomEvent ),
|
|
86
|
+
} );
|
|
87
|
+
} );
|
|
88
|
+
|
|
89
|
+
it( 'should listen to route open', () => {
|
|
90
|
+
// Arrange.
|
|
91
|
+
const routeToListen = 'panel/menu',
|
|
92
|
+
anotherRoute = 'non/related/route',
|
|
93
|
+
callback = jest.fn();
|
|
94
|
+
|
|
95
|
+
// Act.
|
|
96
|
+
listenTo(
|
|
97
|
+
routeOpenEvent( routeToListen ),
|
|
98
|
+
callback
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
// Dispatch the route to test.
|
|
102
|
+
dispatchRouteOpen( routeToListen );
|
|
103
|
+
|
|
104
|
+
// Dispatch another route to make sure we don't listen to it.
|
|
105
|
+
dispatchRouteOpen( anotherRoute );
|
|
106
|
+
|
|
107
|
+
// Assert.
|
|
108
|
+
expect( callback ).toHaveBeenCalledTimes( 1 );
|
|
109
|
+
expect( callback ).toHaveBeenCalledWith( {
|
|
110
|
+
type: 'route',
|
|
111
|
+
route: 'panel/menu',
|
|
112
|
+
originalEvent: expect.any( CustomEvent ),
|
|
113
|
+
} );
|
|
114
|
+
} );
|
|
115
|
+
|
|
116
|
+
it( 'should listen to route close', () => {
|
|
117
|
+
// Arrange.
|
|
118
|
+
const routeToListen = 'panel/menu',
|
|
119
|
+
anotherRoute = 'non/related/route',
|
|
120
|
+
callback = jest.fn();
|
|
121
|
+
|
|
122
|
+
// Act.
|
|
123
|
+
listenTo(
|
|
124
|
+
routeCloseEvent( routeToListen ),
|
|
125
|
+
callback
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
// Dispatch the route to test.
|
|
129
|
+
dispatchRouteClose( routeToListen );
|
|
130
|
+
|
|
131
|
+
// Dispatch another route to make sure we don't listen to it.
|
|
132
|
+
dispatchRouteClose( anotherRoute );
|
|
133
|
+
|
|
134
|
+
// Assert.
|
|
135
|
+
expect( callback ).toHaveBeenCalledTimes( 1 );
|
|
136
|
+
expect( callback ).toHaveBeenCalledWith( {
|
|
137
|
+
type: 'route',
|
|
138
|
+
route: 'panel/menu',
|
|
139
|
+
originalEvent: expect.any( CustomEvent ),
|
|
140
|
+
} );
|
|
141
|
+
} );
|
|
142
|
+
|
|
143
|
+
it( 'should listen to window events', () => {
|
|
144
|
+
// Arrange.
|
|
145
|
+
const event = 'test-event',
|
|
146
|
+
callback = jest.fn();
|
|
147
|
+
|
|
148
|
+
// Act.
|
|
149
|
+
listenTo(
|
|
150
|
+
windowEvent( event ),
|
|
151
|
+
callback
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
// Dispatch events.
|
|
155
|
+
dispatchWindowEvent( event );
|
|
156
|
+
|
|
157
|
+
// Assert.
|
|
158
|
+
expect( callback ).toHaveBeenCalledTimes( 1 );
|
|
159
|
+
expect( callback ).toHaveBeenCalledWith( {
|
|
160
|
+
type: 'window-event',
|
|
161
|
+
event: 'test-event',
|
|
162
|
+
originalEvent: expect.any( Event ),
|
|
163
|
+
} );
|
|
164
|
+
} );
|
|
165
|
+
|
|
166
|
+
it( 'should listen to the same event with multiple callbacks', () => {
|
|
167
|
+
// Arrange.
|
|
168
|
+
const event = 'test-event',
|
|
169
|
+
callback1 = jest.fn(),
|
|
170
|
+
callback2 = jest.fn();
|
|
171
|
+
|
|
172
|
+
// Act.
|
|
173
|
+
listenTo(
|
|
174
|
+
windowEvent( event ),
|
|
175
|
+
callback1
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
listenTo(
|
|
179
|
+
windowEvent( event ),
|
|
180
|
+
callback2
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
// Dispatch events.
|
|
184
|
+
dispatchWindowEvent( event );
|
|
185
|
+
|
|
186
|
+
// Assert.
|
|
187
|
+
expect( callback1 ).toHaveBeenCalledTimes( 1 );
|
|
188
|
+
expect( callback2 ).toHaveBeenCalledTimes( 1 );
|
|
189
|
+
} );
|
|
190
|
+
|
|
191
|
+
it( 'should listen to an array of events', () => {
|
|
192
|
+
// Arrange.
|
|
193
|
+
const command = 'test-command',
|
|
194
|
+
route = 'test-route',
|
|
195
|
+
event = 'test-event',
|
|
196
|
+
callback = jest.fn();
|
|
197
|
+
|
|
198
|
+
// Act.
|
|
199
|
+
listenTo( [
|
|
200
|
+
windowEvent( event ),
|
|
201
|
+
commandStartEvent( command ),
|
|
202
|
+
routeOpenEvent( route ),
|
|
203
|
+
], callback );
|
|
204
|
+
|
|
205
|
+
// Dispatch events.
|
|
206
|
+
dispatchCommandBefore( command );
|
|
207
|
+
dispatchCommandAfter( command );
|
|
208
|
+
|
|
209
|
+
dispatchRouteOpen( route );
|
|
210
|
+
dispatchRouteClose( route );
|
|
211
|
+
|
|
212
|
+
dispatchWindowEvent( event );
|
|
213
|
+
|
|
214
|
+
// Assert.
|
|
215
|
+
expect( callback ).toHaveBeenCalledTimes( 3 );
|
|
216
|
+
|
|
217
|
+
expect( callback ).toHaveBeenNthCalledWith( 1, {
|
|
218
|
+
type: 'command',
|
|
219
|
+
command: 'test-command',
|
|
220
|
+
originalEvent: expect.any( CustomEvent ),
|
|
221
|
+
} );
|
|
222
|
+
|
|
223
|
+
expect( callback ).toHaveBeenNthCalledWith( 2, {
|
|
224
|
+
type: 'route',
|
|
225
|
+
route: 'test-route',
|
|
226
|
+
originalEvent: expect.any( CustomEvent ),
|
|
227
|
+
} );
|
|
228
|
+
|
|
229
|
+
expect( callback ).toHaveBeenNthCalledWith( 3, {
|
|
230
|
+
type: 'window-event',
|
|
231
|
+
event: 'test-event',
|
|
232
|
+
originalEvent: expect.any( Event ),
|
|
233
|
+
} );
|
|
234
|
+
} );
|
|
235
|
+
|
|
236
|
+
it( 'should cleanup listeners', () => {
|
|
237
|
+
// Arrange.
|
|
238
|
+
const event1 = 'test-event-1',
|
|
239
|
+
event2 = 'test-event-2',
|
|
240
|
+
callback1 = jest.fn(),
|
|
241
|
+
callback2 = jest.fn();
|
|
242
|
+
|
|
243
|
+
const cleanup1 = listenTo(
|
|
244
|
+
[
|
|
245
|
+
windowEvent( event1 ),
|
|
246
|
+
windowEvent( event2 ),
|
|
247
|
+
],
|
|
248
|
+
callback1,
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
const cleanup2 = listenTo(
|
|
252
|
+
windowEvent( event1 ),
|
|
253
|
+
callback2,
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
// Act.
|
|
257
|
+
cleanup1();
|
|
258
|
+
cleanup2();
|
|
259
|
+
|
|
260
|
+
// Dispatch events.
|
|
261
|
+
dispatchWindowEvent( event1 );
|
|
262
|
+
dispatchWindowEvent( event2 );
|
|
263
|
+
|
|
264
|
+
// Assert.
|
|
265
|
+
expect( callback1 ).toHaveBeenCalledTimes( 0 );
|
|
266
|
+
expect( callback2 ).toHaveBeenCalledTimes( 0 );
|
|
267
|
+
} );
|
|
268
|
+
|
|
269
|
+
it( 'should not fail when calling the same cleanup twice', () => {
|
|
270
|
+
// Arrange.
|
|
271
|
+
const event = 'test-event',
|
|
272
|
+
callback = jest.fn();
|
|
273
|
+
|
|
274
|
+
const cleanup = listenTo(
|
|
275
|
+
windowEvent( event ),
|
|
276
|
+
callback,
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
// Act.
|
|
280
|
+
cleanup();
|
|
281
|
+
cleanup();
|
|
282
|
+
|
|
283
|
+
// Dispatch events.
|
|
284
|
+
dispatchWindowEvent( event );
|
|
285
|
+
|
|
286
|
+
// Assert.
|
|
287
|
+
expect( callback ).toHaveBeenCalledTimes( 0 );
|
|
288
|
+
} );
|
|
289
|
+
|
|
290
|
+
it( 'should trigger v1 ready when v1 is loaded after v2', async () => {
|
|
291
|
+
// Arrange.
|
|
292
|
+
const callback = jest.fn();
|
|
293
|
+
const extendedWindow = ( window as unknown as ExtendedWindow );
|
|
294
|
+
|
|
295
|
+
extendedWindow.__elementorEditorV1LoadingPromise = new Promise( ( resolve ) => {
|
|
296
|
+
setTimeout( resolve, 1000 );
|
|
297
|
+
} );
|
|
298
|
+
|
|
299
|
+
// Act.
|
|
300
|
+
listenTo(
|
|
301
|
+
v1ReadyEvent(),
|
|
302
|
+
callback
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
dispatchReadyEvent();
|
|
306
|
+
|
|
307
|
+
await jest.runAllTimers();
|
|
308
|
+
|
|
309
|
+
// Assert.
|
|
310
|
+
expect( callback ).toHaveBeenCalledTimes( 1 );
|
|
311
|
+
} );
|
|
312
|
+
|
|
313
|
+
it( 'should not trigger callback when the application is not ready', () => {
|
|
314
|
+
// Arrange
|
|
315
|
+
setReady( false );
|
|
316
|
+
|
|
317
|
+
const event = 'test-event';
|
|
318
|
+
const callback = jest.fn();
|
|
319
|
+
|
|
320
|
+
// Act.
|
|
321
|
+
listenTo(
|
|
322
|
+
windowEvent( event ),
|
|
323
|
+
callback
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
// Dispatch events.
|
|
327
|
+
dispatchWindowEvent( event );
|
|
328
|
+
|
|
329
|
+
// Assert.
|
|
330
|
+
expect( callback ).not.toHaveBeenCalled();
|
|
331
|
+
} );
|
|
332
|
+
|
|
333
|
+
it( 'should throw when v1 is not loaded', async () => {
|
|
334
|
+
// Act & Assert.
|
|
335
|
+
try {
|
|
336
|
+
await dispatchReadyEvent();
|
|
337
|
+
} catch ( e ) {
|
|
338
|
+
expect( e ).toBe( 'Elementor Editor V1 is not loaded' );
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
expect.assertions( 1 );
|
|
342
|
+
} );
|
|
343
|
+
} );
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { CommandEventDescriptor, RouteEventDescriptor, WindowEventDescriptor } from './types';
|
|
2
|
+
|
|
3
|
+
export const commandStartEvent = ( command: CommandEventDescriptor['name'] ): CommandEventDescriptor => {
|
|
4
|
+
return {
|
|
5
|
+
type: 'command',
|
|
6
|
+
name: command,
|
|
7
|
+
state: 'before',
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const commandEndEvent = ( command: CommandEventDescriptor['name'] ): CommandEventDescriptor => {
|
|
12
|
+
return {
|
|
13
|
+
type: 'command',
|
|
14
|
+
name: command,
|
|
15
|
+
state: 'after',
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const routeOpenEvent = ( route: RouteEventDescriptor['name'] ): RouteEventDescriptor => {
|
|
20
|
+
return {
|
|
21
|
+
type: 'route',
|
|
22
|
+
name: route,
|
|
23
|
+
state: 'open',
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const routeCloseEvent = ( route: RouteEventDescriptor['name'] ): RouteEventDescriptor => {
|
|
28
|
+
return {
|
|
29
|
+
type: 'route',
|
|
30
|
+
name: route,
|
|
31
|
+
state: 'close',
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const windowEvent = ( event: WindowEventDescriptor['name'] ): WindowEventDescriptor => {
|
|
36
|
+
return {
|
|
37
|
+
type: 'window-event',
|
|
38
|
+
name: event,
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const v1ReadyEvent = () => {
|
|
43
|
+
return windowEvent( 'elementor/initialized' );
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const editModeChangeEvent = () => {
|
|
47
|
+
return windowEvent( 'elementor/edit-mode/change' );
|
|
48
|
+
};
|