@wordpress/editor 12.17.0 → 12.18.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 CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 12.18.0 (2022-10-05)
6
+
5
7
  ## 12.17.0 (2022-09-21)
6
8
 
7
9
  ## 12.16.0 (2022-09-13)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/editor",
3
- "version": "12.17.0",
3
+ "version": "12.18.0",
4
4
  "description": "Enhanced block editor for WordPress posts.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -31,32 +31,32 @@
31
31
  ],
32
32
  "dependencies": {
33
33
  "@babel/runtime": "^7.16.0",
34
- "@wordpress/a11y": "^3.18.0",
35
- "@wordpress/api-fetch": "^6.15.0",
36
- "@wordpress/blob": "^3.18.0",
37
- "@wordpress/block-editor": "^10.1.0",
38
- "@wordpress/blocks": "^11.17.0",
39
- "@wordpress/components": "^21.1.0",
40
- "@wordpress/compose": "^5.16.0",
41
- "@wordpress/core-data": "^5.1.0",
42
- "@wordpress/data": "^7.2.0",
43
- "@wordpress/date": "^4.18.0",
44
- "@wordpress/deprecated": "^3.18.0",
45
- "@wordpress/element": "^4.16.0",
46
- "@wordpress/hooks": "^3.18.0",
47
- "@wordpress/html-entities": "^3.18.0",
48
- "@wordpress/i18n": "^4.18.0",
49
- "@wordpress/icons": "^9.9.0",
50
- "@wordpress/keyboard-shortcuts": "^3.16.0",
51
- "@wordpress/keycodes": "^3.18.0",
52
- "@wordpress/media-utils": "^4.9.0",
53
- "@wordpress/notices": "^3.18.0",
54
- "@wordpress/preferences": "^2.10.0",
55
- "@wordpress/reusable-blocks": "^3.16.0",
56
- "@wordpress/rich-text": "^5.16.0",
57
- "@wordpress/server-side-render": "^3.16.0",
58
- "@wordpress/url": "^3.19.0",
59
- "@wordpress/wordcount": "^3.18.0",
34
+ "@wordpress/a11y": "^3.19.0",
35
+ "@wordpress/api-fetch": "^6.16.0",
36
+ "@wordpress/blob": "^3.19.0",
37
+ "@wordpress/block-editor": "^10.2.0",
38
+ "@wordpress/blocks": "^11.18.0",
39
+ "@wordpress/components": "^21.2.0",
40
+ "@wordpress/compose": "^5.17.0",
41
+ "@wordpress/core-data": "^5.2.0",
42
+ "@wordpress/data": "^7.3.0",
43
+ "@wordpress/date": "^4.19.0",
44
+ "@wordpress/deprecated": "^3.19.0",
45
+ "@wordpress/element": "^4.17.0",
46
+ "@wordpress/hooks": "^3.19.0",
47
+ "@wordpress/html-entities": "^3.19.0",
48
+ "@wordpress/i18n": "^4.19.0",
49
+ "@wordpress/icons": "^9.10.0",
50
+ "@wordpress/keyboard-shortcuts": "^3.17.0",
51
+ "@wordpress/keycodes": "^3.19.0",
52
+ "@wordpress/media-utils": "^4.10.0",
53
+ "@wordpress/notices": "^3.19.0",
54
+ "@wordpress/preferences": "^2.11.0",
55
+ "@wordpress/reusable-blocks": "^3.17.0",
56
+ "@wordpress/rich-text": "^5.17.0",
57
+ "@wordpress/server-side-render": "^3.17.0",
58
+ "@wordpress/url": "^3.20.0",
59
+ "@wordpress/wordcount": "^3.19.0",
60
60
  "classnames": "^2.3.1",
61
61
  "lodash": "^4.17.21",
62
62
  "memize": "^1.1.0",
@@ -71,5 +71,5 @@
71
71
  "publishConfig": {
72
72
  "access": "public"
73
73
  },
74
- "gitHead": "23e136283fa1d3b8d9d8b33869f871ad5eb77726"
74
+ "gitHead": "8d42d2febb7d0ba8372a33e560a62f5a5f6a9112"
75
75
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { shallow } from 'enzyme';
4
+ import { render } from '@testing-library/react';
5
5
 
6
6
  /**
7
7
  * Internal dependencies
@@ -9,7 +9,6 @@ import { shallow } from 'enzyme';
9
9
  import { AutosaveMonitor } from '../';
10
10
 
11
11
  describe( 'AutosaveMonitor', () => {
12
- let wrapper;
13
12
  let setAutosaveTimerSpy;
14
13
  beforeEach( () => {
15
14
  jest.useFakeTimers( 'legacy' );
@@ -17,9 +16,6 @@ describe( 'AutosaveMonitor', () => {
17
16
  AutosaveMonitor.prototype,
18
17
  'setAutosaveTimer'
19
18
  );
20
- wrapper = shallow( <AutosaveMonitor isDirty />, {
21
- lifecycleExperimental: true,
22
- } );
23
19
  } );
24
20
 
25
21
  afterEach( () => {
@@ -29,128 +25,167 @@ describe( 'AutosaveMonitor', () => {
29
25
  setAutosaveTimerSpy.mockClear();
30
26
  } );
31
27
 
28
+ it( 'should render nothing', () => {
29
+ const { container } = render( <AutosaveMonitor isDirty /> );
30
+
31
+ expect( container ).toBeEmptyDOMElement();
32
+ } );
33
+
32
34
  it( 'should start autosave timer after being mounted', () => {
35
+ render( <AutosaveMonitor isDirty /> );
36
+
33
37
  expect( setAutosaveTimerSpy ).toHaveBeenCalled();
34
38
  } );
35
39
 
36
40
  it( 'should clear the autosave timer after being unmounted', () => {
37
- wrapper.unmount();
41
+ const { rerender } = render( <AutosaveMonitor isDirty /> );
42
+
43
+ rerender( <div /> );
44
+
45
+ expect( clearTimeout ).toHaveBeenCalled();
46
+ } );
47
+
48
+ it( 'should clear and restart autosave timer when the interval changes', () => {
49
+ const { rerender } = render( <AutosaveMonitor isDirty /> );
50
+
51
+ rerender( <AutosaveMonitor isDirty interval={ 999 } /> );
52
+
38
53
  expect( clearTimeout ).toHaveBeenCalled();
54
+ expect( setAutosaveTimerSpy ).toHaveBeenCalledTimes( 2 );
39
55
  } );
40
56
 
41
- describe( '#componentDidUpdate()', () => {
42
- it( 'should clear and restart autosave timer when the interval changes', () => {
43
- wrapper.setProps( { interval: 999 } );
44
- expect( clearTimeout ).toHaveBeenCalled();
45
- expect( setAutosaveTimerSpy ).toHaveBeenCalledTimes( 2 );
46
- } );
47
-
48
- it( 'should set needsAutosave=true when editReference changes', () => {
49
- expect( wrapper.instance().needsAutosave ).toBe( false );
50
- wrapper.setProps( {
51
- editsReference: [],
52
- } );
53
- expect( wrapper.instance().needsAutosave ).toBe( true );
54
- } );
55
-
56
- it( 'should set needsAutosave=true when editReference changes and the post becomes dirty', () => {
57
- expect( wrapper.instance().needsAutosave ).toBe( false );
58
- wrapper.setProps( {
59
- isDirty: true,
60
- editsReference: [],
61
- } );
62
- expect( wrapper.instance().needsAutosave ).toBe( true );
63
- } );
64
-
65
- it( 'should not set needsAutosave=true when editReference changes and the post is not dirty anymore', () => {
66
- expect( wrapper.instance().needsAutosave ).toBe( false );
67
- wrapper.setProps( {
68
- isDirty: true,
69
- editsReference: [],
70
- } );
71
- wrapper.setProps( {
72
- isDirty: false,
73
- editsReference: [],
74
- } );
75
- expect( wrapper.instance().needsAutosave ).toBe( false );
76
- } );
77
-
78
- it( 'should set needsAutosave=true when editReference changes and the post is not autosaving', () => {
79
- expect( wrapper.instance().needsAutosave ).toBe( false );
80
- wrapper.setProps( {
81
- isAutosaving: false,
82
- editsReference: [],
83
- } );
84
- expect( wrapper.instance().needsAutosave ).toBe( true );
85
- } );
86
-
87
- it( 'should not set needsAutosave=true when editReference changes and the post started autosaving', () => {
88
- expect( wrapper.instance().needsAutosave ).toBe( false );
89
- wrapper.setProps( {
90
- isAutosaving: false,
91
- editsReference: [],
92
- } );
93
- wrapper.setProps( {
94
- isAutosaving: true,
95
- editsReference: [],
96
- } );
97
- expect( wrapper.instance().needsAutosave ).toBe( false );
98
- } );
57
+ it( 'should autosave when `editReference` changes', () => {
58
+ const autosave = jest.fn();
59
+ const { rerender } = render(
60
+ <AutosaveMonitor isDirty isAutosaveable autosave={ autosave } />
61
+ );
62
+
63
+ expect( autosave ).not.toHaveBeenCalled();
64
+
65
+ rerender(
66
+ <AutosaveMonitor
67
+ isDirty
68
+ isAutosaveable
69
+ autosave={ autosave }
70
+ editsReference={ [] }
71
+ />
72
+ );
73
+
74
+ jest.runOnlyPendingTimers();
75
+
76
+ expect( autosave ).toHaveBeenCalledTimes( 1 );
99
77
  } );
100
78
 
101
- describe( '#autosaveTimerHandler()', () => {
102
- it( 'should schedule itself in another {interval} ms', () => {
103
- wrapper.setProps( {
104
- isAutosaveable: true,
105
- interval: 5,
106
- } );
107
- expect( setAutosaveTimerSpy ).toHaveBeenCalledTimes( 2 );
108
- wrapper.instance().autosaveTimerHandler();
109
- expect( setAutosaveTimerSpy ).toHaveBeenCalledTimes( 3 );
110
- expect( setTimeout ).lastCalledWith( expect.any( Function ), 5000 );
111
- } );
112
-
113
- it( 'should schedule itself in 1000 ms if the post is not autosaveable at a time', () => {
114
- wrapper.setProps( {
115
- isAutosaveable: false,
116
- interval: 5,
117
- } );
118
- expect( setAutosaveTimerSpy ).toHaveBeenCalledTimes( 2 );
119
- wrapper.instance().autosaveTimerHandler();
120
- expect( setAutosaveTimerSpy ).toHaveBeenCalledTimes( 3 );
121
- expect( setTimeout ).lastCalledWith( expect.any( Function ), 1000 );
122
- } );
123
-
124
- it( 'should call autosave if needsAutosave=true', () => {
125
- const autosave = jest.fn();
126
- wrapper.setProps( {
127
- isAutosaveable: true,
128
- interval: 5,
129
- autosave,
130
- } );
131
- wrapper.instance().needsAutosave = true;
132
- expect( autosave ).toHaveBeenCalledTimes( 0 );
133
- wrapper.instance().autosaveTimerHandler();
134
- expect( autosave ).toHaveBeenCalledTimes( 1 );
135
- } );
136
-
137
- it( 'should not call autosave if needsAutosave is not true', () => {
138
- const autosave = jest.fn();
139
- wrapper.setProps( {
140
- isAutosaveable: true,
141
- interval: 5,
142
- autosave,
143
- } );
144
- wrapper.instance().needsAutosave = false;
145
- expect( autosave ).toHaveBeenCalledTimes( 0 );
146
- wrapper.instance().autosaveTimerHandler();
147
- expect( autosave ).toHaveBeenCalledTimes( 0 );
148
- } );
79
+ it( 'should autosave when `editReference` changes and the post becomes dirty', () => {
80
+ const autosave = jest.fn();
81
+ const { rerender } = render(
82
+ <AutosaveMonitor isAutosaveable autosave={ autosave } />
83
+ );
84
+
85
+ expect( autosave ).not.toHaveBeenCalled();
86
+
87
+ rerender(
88
+ <AutosaveMonitor
89
+ isDirty
90
+ isAutosaveable
91
+ autosave={ autosave }
92
+ editsReference={ [] }
93
+ />
94
+ );
95
+
96
+ jest.runOnlyPendingTimers();
97
+
98
+ expect( autosave ).toHaveBeenCalledTimes( 1 );
149
99
  } );
150
100
 
151
- describe( '#render()', () => {
152
- it( 'should render nothing', () => {
153
- expect( wrapper.type() ).toBe( null );
154
- } );
101
+ it( 'should not autosave when `editReference` changes and the post is not dirty anymore', () => {
102
+ const autosave = jest.fn();
103
+ const { rerender } = render(
104
+ <AutosaveMonitor isDirty isAutosaveable autosave={ autosave } />
105
+ );
106
+
107
+ expect( autosave ).not.toHaveBeenCalled();
108
+
109
+ rerender(
110
+ <AutosaveMonitor
111
+ isAutosaveable
112
+ autosave={ autosave }
113
+ editsReference={ [] }
114
+ />
115
+ );
116
+
117
+ jest.runOnlyPendingTimers();
118
+
119
+ expect( autosave ).not.toHaveBeenCalled();
120
+ } );
121
+
122
+ it( 'should not autosave when `editReference` changes and the post is not autosaving', () => {
123
+ const autosave = jest.fn();
124
+ const { rerender } = render(
125
+ <AutosaveMonitor isAutosaveable autosave={ autosave } />
126
+ );
127
+
128
+ expect( autosave ).not.toHaveBeenCalled();
129
+
130
+ rerender(
131
+ <AutosaveMonitor
132
+ isAutosaveable
133
+ autosave={ autosave }
134
+ isAutosaving={ false }
135
+ editsReference={ [] }
136
+ />
137
+ );
138
+
139
+ jest.runOnlyPendingTimers();
140
+
141
+ expect( autosave ).not.toHaveBeenCalled();
142
+ } );
143
+
144
+ it( 'should not autosave when `editReference` changes and the post started autosaving', () => {
145
+ const autosave = jest.fn();
146
+ const { rerender } = render(
147
+ <AutosaveMonitor
148
+ isAutosaveable
149
+ autosave={ autosave }
150
+ isAutosaving={ false }
151
+ />
152
+ );
153
+
154
+ expect( autosave ).not.toHaveBeenCalled();
155
+
156
+ rerender(
157
+ <AutosaveMonitor
158
+ isAutosaveable
159
+ autosave={ autosave }
160
+ isAutosaving
161
+ editsReference={ [] }
162
+ />
163
+ );
164
+
165
+ jest.runOnlyPendingTimers();
166
+
167
+ expect( autosave ).not.toHaveBeenCalled();
168
+ } );
169
+
170
+ it( 'should schedule itself in another {interval} ms', () => {
171
+ const { rerender } = render( <AutosaveMonitor isDirty /> );
172
+
173
+ rerender( <AutosaveMonitor isDirty isAutosaveable interval={ 5 } /> );
174
+
175
+ jest.runOnlyPendingTimers();
176
+
177
+ expect( setTimeout ).lastCalledWith( expect.any( Function ), 5000 );
178
+ } );
179
+
180
+ it( 'should schedule itself in 1000 ms if the post is not autosaveable at a time', () => {
181
+ const { rerender } = render( <AutosaveMonitor isDirty /> );
182
+
183
+ rerender(
184
+ <AutosaveMonitor isDirty isAutosaveable={ false } interval={ 5 } />
185
+ );
186
+
187
+ jest.runOnlyPendingTimers();
188
+
189
+ expect( setTimeout ).lastCalledWith( expect.any( Function ), 1000 );
155
190
  } );
156
191
  } );
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { shallow } from 'enzyme';
4
+ import { render, screen, within } from '@testing-library/react';
5
+ import userEvent from '@testing-library/user-event';
5
6
 
6
7
  /**
7
8
  * Internal dependencies
@@ -9,180 +10,310 @@ import { shallow } from 'enzyme';
9
10
  import { PostPreviewButton } from '../';
10
11
 
11
12
  describe( 'PostPreviewButton', () => {
12
- describe( 'setPreviewWindowLink()', () => {
13
- it( 'should do nothing if there is no preview window', () => {
14
- const url = 'https://wordpress.org';
15
- const setter = jest.fn();
16
- const wrapper = shallow( <PostPreviewButton /> );
13
+ const documentWrite = jest.fn();
14
+ const documentTitle = jest.fn();
15
+ const documentClose = jest.fn();
16
+ const setLocation = jest.fn();
17
17
 
18
- wrapper.instance().setPreviewWindowLink( url );
18
+ beforeEach( () => {
19
+ global.open = jest.fn( () => ( {
20
+ focus: jest.fn(),
21
+ document: {
22
+ write: documentWrite,
23
+ close: documentClose,
24
+ get title() {},
25
+ set title( value ) {
26
+ documentTitle( value );
27
+ },
28
+ },
29
+ get location() {},
30
+ set location( value ) {
31
+ setLocation( value );
32
+ },
33
+ } ) );
34
+ } );
19
35
 
20
- expect( setter ).not.toHaveBeenCalled();
21
- } );
36
+ afterEach( () => {
37
+ global.open.mockRestore();
38
+ documentWrite.mockReset();
39
+ documentTitle.mockReset();
40
+ documentClose.mockReset();
41
+ setLocation.mockReset();
42
+ } );
22
43
 
23
- it( 'set preview window location to url', () => {
24
- const url = 'https://wordpress.org';
25
- const setter = jest.fn();
26
- const wrapper = shallow( <PostPreviewButton /> );
27
- wrapper.instance().previewWindow = {
28
- get location() {
29
- return {
30
- href: 'about:blank',
31
- };
32
- },
33
- set location( value ) {
34
- setter( value );
35
- },
36
- };
44
+ it( 'should render with `editor-post-preview` class if no `className` is specified.', () => {
45
+ render( <PostPreviewButton /> );
37
46
 
38
- wrapper.instance().setPreviewWindowLink( url );
47
+ expect( screen.getByRole( 'button' ) ).toHaveClass(
48
+ 'editor-post-preview'
49
+ );
50
+ } );
39
51
 
40
- expect( setter ).toHaveBeenCalledWith( url );
41
- } );
52
+ it( 'should render with a custom class and not `editor-post-preview` if `className` is specified.', () => {
53
+ render( <PostPreviewButton className="foo-bar" /> );
54
+
55
+ const button = screen.getByRole( 'button' );
56
+
57
+ expect( button ).toHaveClass( 'foo-bar' );
58
+ expect( button ).not.toHaveClass( 'editor-post-preview' );
42
59
  } );
43
60
 
44
- describe( 'getWindowTarget()', () => {
45
- it( 'returns a string unique to the post id', () => {
46
- const instance = new PostPreviewButton( {
47
- postId: 1,
48
- } );
61
+ it( 'should render a tertiary button if no classname is specified.', () => {
62
+ render( <PostPreviewButton /> );
49
63
 
50
- expect( instance.getWindowTarget() ).toBe( 'wp-preview-1' );
51
- } );
64
+ expect( screen.getByRole( 'button' ) ).toHaveClass( 'is-tertiary' );
52
65
  } );
53
66
 
54
- describe( 'componentDidUpdate()', () => {
55
- it( 'should change popup location if preview link is available', () => {
56
- const wrapper = shallow(
57
- <PostPreviewButton
58
- postId={ 1 }
59
- currentPostLink="https://wordpress.org/?p=1"
60
- isSaveable
61
- modified="2017-08-03T15:05:50"
62
- />
63
- );
67
+ it( 'should render the button in its default variant if a custom classname is specified.', () => {
68
+ render( <PostPreviewButton className="foo-bar" /> );
69
+
70
+ const button = screen.getByRole( 'button' );
64
71
 
65
- const previewWindow = { location: {} };
72
+ expect( button ).not.toHaveClass( 'is-primary' );
73
+ expect( button ).not.toHaveClass( 'is-secondary' );
74
+ expect( button ).not.toHaveClass( 'is-tertiary' );
75
+ expect( button ).not.toHaveClass( 'is-link' );
76
+ } );
66
77
 
67
- wrapper.instance().previewWindow = previewWindow;
78
+ it( 'should render `textContent` if specified.', () => {
79
+ const textContent = 'Foo bar';
68
80
 
69
- wrapper.setProps( { previewLink: 'https://wordpress.org/?p=1' } );
81
+ render( <PostPreviewButton textContent={ textContent } /> );
70
82
 
71
- expect( previewWindow.location ).toBe(
72
- 'https://wordpress.org/?p=1'
73
- );
74
- } );
83
+ const button = screen.getByRole( 'button' );
84
+
85
+ expect( button ).toHaveTextContent( textContent );
86
+ expect(
87
+ within( button ).queryByText( 'Preview' )
88
+ ).not.toBeInTheDocument();
89
+ expect(
90
+ within( button ).queryByText( '(opens in a new tab)' )
91
+ ).not.toBeInTheDocument();
75
92
  } );
76
93
 
77
- describe( 'openPreviewWindow()', () => {
78
- let windowOpen;
79
- beforeEach( () => {
80
- windowOpen = window.open;
81
- } );
82
- afterEach( () => {
83
- window.open = windowOpen;
84
- } );
94
+ it( 'should render `Preview` with accessibility text if `textContent` not specified.', () => {
95
+ render( <PostPreviewButton /> );
85
96
 
86
- it( 'behaves like a regular link if not autosaveable', () => {
87
- const preventDefault = jest.fn();
88
- const autosave = jest.fn();
89
- const setLocation = jest.fn();
90
- window.open = jest.fn( () => ( {
91
- focus: jest.fn(),
92
- set location( url ) {
93
- setLocation( url );
94
- },
95
- } ) );
96
-
97
- const wrapper = shallow(
98
- <PostPreviewButton postId={ 1 } autosave={ autosave } />
99
- );
100
-
101
- wrapper.simulate( 'click', {
102
- preventDefault,
103
- target: { href: 'https://wordpress.org/?p=1' },
104
- } );
105
-
106
- expect( preventDefault ).toHaveBeenCalled();
107
- expect( window.open ).toHaveBeenCalledWith( '', 'wp-preview-1' );
108
- expect( wrapper.instance().previewWindow.focus ).toHaveBeenCalled();
109
- expect( autosave ).not.toHaveBeenCalled();
110
- expect( setLocation ).toHaveBeenCalledWith(
111
- 'https://wordpress.org/?p=1'
112
- );
113
- } );
97
+ const button = screen.getByRole( 'button' );
98
+
99
+ expect( within( button ).getByText( 'Preview' ) ).toBeVisible();
100
+ expect(
101
+ within( button ).getByText( '(opens in a new tab)' )
102
+ ).toBeInTheDocument();
103
+ } );
114
104
 
115
- it( 'autosaves the post if autosaveable', () => {
116
- const preventDefault = jest.fn();
117
- const autosave = jest.fn();
105
+ it( 'should be disabled if post is not saveable.', async () => {
106
+ render( <PostPreviewButton isSaveable={ false } postId={ 123 } /> );
118
107
 
119
- window.open = jest.fn( () => ( {
120
- focus: jest.fn(),
121
- document: {
122
- write: jest.fn(),
123
- close: jest.fn(),
124
- },
125
- } ) );
126
-
127
- const wrapper = shallow(
128
- <PostPreviewButton
129
- postId={ 1 }
130
- autosave={ autosave }
131
- isAutosaveable
132
- />
133
- );
134
-
135
- wrapper.simulate( 'click', { preventDefault } );
136
-
137
- expect( preventDefault ).toHaveBeenCalled();
138
- expect( window.open ).toHaveBeenCalledWith( '', 'wp-preview-1' );
139
- expect( wrapper.instance().previewWindow.focus ).toHaveBeenCalled();
140
- expect( autosave ).toHaveBeenCalled();
141
- expect(
142
- wrapper.instance().previewWindow.document.write.mock
143
- .calls[ 0 ][ 0 ]
144
- ).toContain( 'Generating preview…' );
145
- expect(
146
- wrapper.instance().previewWindow.document.close
147
- ).toHaveBeenCalled();
108
+ expect( screen.getByRole( 'button' ) ).toBeDisabled();
109
+ } );
110
+
111
+ it( 'should not be disabled if post is saveable.', async () => {
112
+ render( <PostPreviewButton isSaveable postId={ 123 } /> );
113
+
114
+ expect( screen.getByRole( 'button' ) ).not.toBeDisabled();
115
+ } );
116
+
117
+ it( 'should set `href` to `previewLink` if `previewLink` is specified.', async () => {
118
+ const url = 'https://wordpress.org';
119
+
120
+ render(
121
+ <PostPreviewButton isSaveable postId={ 123 } previewLink={ url } />
122
+ );
123
+
124
+ expect( screen.getByRole( 'link' ) ).toHaveAttribute( 'href', url );
125
+ } );
126
+
127
+ it( 'should set `href` to `currentPostLink` if `currentPostLink` is specified.', async () => {
128
+ const url = 'https://wordpress.org';
129
+
130
+ render(
131
+ <PostPreviewButton
132
+ isSaveable
133
+ postId={ 123 }
134
+ currentPostLink={ url }
135
+ />
136
+ );
137
+
138
+ expect( screen.getByRole( 'link' ) ).toHaveAttribute( 'href', url );
139
+ } );
140
+
141
+ it( 'should prioritize `previewLink` if both `previewLink` and `currentPostLink` are specified.', async () => {
142
+ const url1 = 'https://wordpress.org';
143
+ const url2 = 'https://wordpress.com';
144
+
145
+ render(
146
+ <PostPreviewButton
147
+ isSaveable
148
+ postId={ 123 }
149
+ previewLink={ url1 }
150
+ currentPostLink={ url2 }
151
+ />
152
+ );
153
+
154
+ expect( screen.getByRole( 'link' ) ).toHaveAttribute( 'href', url1 );
155
+ } );
156
+
157
+ it( 'should properly set target to `wp-preview-${ postId }`.', async () => {
158
+ const postId = 123;
159
+ const url = 'https://wordpress.org';
160
+
161
+ render(
162
+ <PostPreviewButton
163
+ isSaveable
164
+ postId={ postId }
165
+ previewLink={ url }
166
+ />
167
+ );
168
+
169
+ expect( screen.getByRole( 'link' ) ).toHaveAttribute(
170
+ 'target',
171
+ `wp-preview-${ postId }`
172
+ );
173
+ } );
174
+
175
+ it( 'should save post if `isDraft` is `true`', async () => {
176
+ const user = userEvent.setup( {
177
+ advanceTimers: jest.advanceTimersByTime,
148
178
  } );
179
+ const url = 'https://wordpress.org';
180
+ const savePost = jest.fn();
181
+ const autosave = jest.fn();
182
+
183
+ render(
184
+ <PostPreviewButton
185
+ isAutosaveable
186
+ isSaveable
187
+ isDraft
188
+ postId={ 123 }
189
+ previewLink={ url }
190
+ savePost={ savePost }
191
+ autosave={ autosave }
192
+ />
193
+ );
194
+
195
+ await user.click( screen.getByRole( 'link' ) );
196
+
197
+ expect( savePost ).toHaveBeenCalledWith(
198
+ expect.objectContaining( { isPreview: true } )
199
+ );
200
+ expect( autosave ).not.toHaveBeenCalled();
149
201
  } );
150
202
 
151
- describe( 'render()', () => {
152
- it( 'should render previewLink if provided', () => {
153
- const wrapper = shallow(
154
- <PostPreviewButton
155
- postId={ 1 }
156
- isSaveable
157
- previewLink="https://wordpress.org/?p=1&preview=true"
158
- currentPostLink="https://wordpress.org/?p=1"
159
- />
160
- );
203
+ it( 'should autosave post if `isDraft` is `false`', async () => {
204
+ const user = userEvent.setup( {
205
+ advanceTimers: jest.advanceTimersByTime,
206
+ } );
207
+ const url = 'https://wordpress.org';
208
+ const savePost = jest.fn();
209
+ const autosave = jest.fn();
161
210
 
162
- expect( wrapper ).toMatchSnapshot();
211
+ render(
212
+ <PostPreviewButton
213
+ isAutosaveable
214
+ isSaveable
215
+ isDraft={ false }
216
+ postId={ 123 }
217
+ previewLink={ url }
218
+ savePost={ savePost }
219
+ autosave={ autosave }
220
+ />
221
+ );
222
+
223
+ await user.click( screen.getByRole( 'link' ) );
224
+
225
+ expect( savePost ).not.toHaveBeenCalled();
226
+ expect( autosave ).toHaveBeenCalledWith(
227
+ expect.objectContaining( { isPreview: true } )
228
+ );
229
+ } );
230
+
231
+ it( 'should open a window with the specified target', async () => {
232
+ const user = userEvent.setup( {
233
+ advanceTimers: jest.advanceTimersByTime,
163
234
  } );
235
+ const postId = 123;
236
+ const url = 'https://wordpress.org';
164
237
 
165
- it( 'should render currentPostLink otherwise', () => {
166
- const wrapper = shallow(
167
- <PostPreviewButton
168
- postId={ 1 }
169
- isSaveable
170
- currentPostLink="https://wordpress.org/?p=1"
171
- />
172
- );
238
+ render(
239
+ <PostPreviewButton
240
+ isAutosaveable
241
+ isSaveable
242
+ postId={ postId }
243
+ previewLink={ url }
244
+ savePost={ jest.fn() }
245
+ autosave={ jest.fn() }
246
+ />
247
+ );
173
248
 
174
- expect( wrapper ).toMatchSnapshot();
249
+ await user.click( screen.getByRole( 'link' ) );
250
+
251
+ expect( global.open ).toHaveBeenCalledWith(
252
+ '',
253
+ `wp-preview-${ postId }`
254
+ );
255
+ } );
256
+
257
+ it( 'should set the location in the window properly', async () => {
258
+ const user = userEvent.setup( {
259
+ advanceTimers: jest.advanceTimersByTime,
175
260
  } );
261
+ const postId = 123;
262
+ const url = 'https://wordpress.org';
263
+
264
+ const { rerender } = render(
265
+ <PostPreviewButton
266
+ isSaveable
267
+ postId={ postId }
268
+ savePost={ jest.fn() }
269
+ autosave={ jest.fn() }
270
+ />
271
+ );
176
272
 
177
- it( 'should be disabled if post is not saveable', () => {
178
- const wrapper = shallow(
179
- <PostPreviewButton
180
- postId={ 1 }
181
- currentPostLink="https://wordpress.org/?p=1"
182
- />
183
- );
273
+ await user.click( screen.getByRole( 'button' ) );
184
274
 
185
- expect( wrapper.prop( 'disabled' ) ).toBe( true );
275
+ expect( setLocation ).toHaveBeenCalledWith( undefined );
276
+
277
+ rerender(
278
+ <PostPreviewButton
279
+ isSaveable
280
+ postId={ postId }
281
+ previewLink={ url }
282
+ savePost={ jest.fn() }
283
+ autosave={ jest.fn() }
284
+ />
285
+ );
286
+
287
+ expect( setLocation ).toHaveBeenCalledWith( url );
288
+ } );
289
+
290
+ it( 'should display a `Generating preview` message while waiting for autosaving', async () => {
291
+ const user = userEvent.setup( {
292
+ advanceTimers: jest.advanceTimersByTime,
186
293
  } );
294
+ const previewText = 'Generating preview…';
295
+ const url = 'https://wordpress.org';
296
+ const savePost = jest.fn();
297
+ const autosave = jest.fn();
298
+
299
+ render(
300
+ <PostPreviewButton
301
+ isAutosaveable
302
+ isSaveable
303
+ isDraft={ false }
304
+ postId={ 123 }
305
+ previewLink={ url }
306
+ savePost={ savePost }
307
+ autosave={ autosave }
308
+ />
309
+ );
310
+
311
+ await user.click( screen.getByRole( 'link' ) );
312
+
313
+ expect( documentWrite ).toHaveBeenCalledWith(
314
+ expect.stringContaining( previewText )
315
+ );
316
+ expect( documentTitle ).toHaveBeenCalledWith( previewText );
317
+ expect( documentClose ).toHaveBeenCalled();
187
318
  } );
188
319
  } );
@@ -1,37 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`PostPreviewButton render() should render currentPostLink otherwise 1`] = `
4
- <ForwardRef(Button)
5
- className="editor-post-preview"
6
- disabled={false}
7
- href="https://wordpress.org/?p=1"
8
- onClick={[Function]}
9
- target="wp-preview-1"
10
- variant="tertiary"
11
- >
12
- Preview
13
- <VisuallyHidden
14
- as="span"
15
- >
16
- (opens in a new tab)
17
- </VisuallyHidden>
18
- </ForwardRef(Button)>
19
- `;
20
-
21
- exports[`PostPreviewButton render() should render previewLink if provided 1`] = `
22
- <ForwardRef(Button)
23
- className="editor-post-preview"
24
- disabled={false}
25
- href="https://wordpress.org/?p=1&preview=true"
26
- onClick={[Function]}
27
- target="wp-preview-1"
28
- variant="tertiary"
29
- >
30
- Preview
31
- <VisuallyHidden
32
- as="span"
33
- >
34
- (opens in a new tab)
35
- </VisuallyHidden>
36
- </ForwardRef(Button)>
37
- `;