-
Notifications
You must be signed in to change notification settings - Fork 4.3k
/
Copy pathinserter.js
237 lines (219 loc) · 7.85 KB
/
inserter.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
/**
* Internal dependencies
*/
import { pressKeyWithModifier } from './press-key-with-modifier';
import { canvas } from './canvas';
// This selector is written to support the current and old inserter markup
// because the performance tests need to be able to run across versions.
const INSERTER_SEARCH_SELECTOR =
'.block-editor-inserter__search input,.block-editor-inserter__search-input,input.block-editor-inserter__search';
/**
* Opens the global block inserter.
*/
export async function openGlobalBlockInserter() {
if ( await isGlobalInserterOpen() ) {
// If global inserter is already opened, reset to an initial state where
// the default (first) tab is selected.
const tab = await page.$(
'.block-editor-inserter__tabs .components-tab-panel__tabs-item:nth-of-type(1):not(.is-active)'
);
if ( tab ) {
await tab.click();
}
} else {
await toggleGlobalBlockInserter();
// Waiting here is necessary because sometimes the inserter takes more time to
// render than Puppeteer takes to complete the 'click' action.
await page.waitForSelector( '.block-editor-inserter__menu' );
}
}
export async function closeGlobalBlockInserter() {
if ( await isGlobalInserterOpen() ) {
await toggleGlobalBlockInserter();
}
}
async function isGlobalInserterOpen() {
return await page.evaluate( () => {
// "Add block" selector is required to make sure performance comparison
// doesn't fail on older branches where we still had "Add block" as label.
return !! document.querySelector(
'.edit-post-header [aria-label="Add block"].is-pressed,' +
'.edit-site-header [aria-label="Add block"].is-pressed,' +
'.edit-post-header [aria-label="Toggle block inserter"].is-pressed,' +
'.edit-site-header [aria-label="Toggle block inserter"].is-pressed,' +
'.edit-widgets-header [aria-label="Toggle block inserter"].is-pressed,' +
'.edit-widgets-header [aria-label="Add block"].is-pressed'
);
} );
}
/**
* Toggles the global inserter.
*/
export async function toggleGlobalBlockInserter() {
// "Add block" selector is required to make sure performance comparison
// doesn't fail on older branches where we still had "Add block" as label.
await page.click(
'.edit-post-header [aria-label="Add block"],' +
'.edit-site-header [aria-label="Add block"],' +
'.edit-post-header [aria-label="Toggle block inserter"],' +
'.edit-site-header [aria-label="Toggle block inserter"],' +
'.edit-widgets-header [aria-label="Add block"],' +
'.edit-widgets-header [aria-label="Toggle block inserter"]'
);
}
/**
* Moves focus to the selected block.
*/
async function focusSelectedBlock() {
// Ideally there shouuld be a UI way to do this. (Focus the selected block)
await page.evaluate( () => {
wp.data
.dispatch( 'core/block-editor' )
.selectBlock(
wp.data
.select( 'core/block-editor' )
.getSelectedBlockClientId(),
0
);
} );
}
/**
* Retrieves the document container by css class and checks to make sure the document's active element is within it
*/
async function waitForInserterCloseAndContentFocus() {
await canvas().waitForFunction(
() =>
document.activeElement.closest(
'.block-editor-block-list__layout'
) !== null
);
}
/**
* Search for block in the global inserter
*
* @param {string} searchTerm The text to search the inserter for.
*/
export async function searchForBlock( searchTerm ) {
await openGlobalBlockInserter();
await page.waitForSelector( INSERTER_SEARCH_SELECTOR );
await page.focus( INSERTER_SEARCH_SELECTOR );
await pressKeyWithModifier( 'primary', 'a' );
await page.keyboard.type( searchTerm );
}
/**
* Search for pattern in the global inserter
*
* @param {string} searchTerm The text to search the inserter for.
*/
export async function searchForPattern( searchTerm ) {
await openGlobalBlockInserter();
// Select the patterns tab.
const tab = await page.waitForXPath(
'//div[contains(@class, "block-editor-inserter__tabs")]//button[.="Patterns"]'
);
await tab.click();
await page.waitForSelector( INSERTER_SEARCH_SELECTOR );
await page.focus( INSERTER_SEARCH_SELECTOR );
await pressKeyWithModifier( 'primary', 'a' );
await page.keyboard.type( searchTerm );
}
/**
* Search for reusable block in the global inserter.
*
* @param {string} searchTerm The text to search the inserter for.
*/
export async function searchForReusableBlock( searchTerm ) {
await openGlobalBlockInserter();
// The reusable blocks tab won't appear until the reusable blocks have been
// fetched. They aren't fetched until an inserter is used or the post
// already contains reusable blocks, so wait for the tab to appear.
await page.waitForXPath(
'//div[contains(@class, "block-editor-inserter__tabs")]//button[text()="Reusable"]'
);
// Select the reusable blocks tab.
const tab = await page.waitForXPath(
'//div[contains(@class, "block-editor-inserter__tabs")]//button[text()="Reusable"]'
);
await tab.click();
await page.waitForSelector( INSERTER_SEARCH_SELECTOR );
await page.focus( INSERTER_SEARCH_SELECTOR );
await pressKeyWithModifier( 'primary', 'a' );
await page.keyboard.type( searchTerm );
}
/**
* Opens the inserter, searches for the given term, then selects the first
* result that appears. It then waits briefly for the block list to update.
*
* @param {string} searchTerm The text to search the inserter for.
*/
export async function insertBlock( searchTerm ) {
await searchForBlock( searchTerm );
const insertButton = await page.waitForXPath(
`//button//span[contains(text(), '${ searchTerm }')]`
);
await insertButton.click();
await focusSelectedBlock();
// We should wait until the inserter closes and the focus moves to the content.
await waitForInserterCloseAndContentFocus();
}
/**
* Opens the inserter, searches for the given pattern, then selects the first
* result that appears. It then waits briefly for the block list to update.
*
* @param {string} searchTerm The text to search the inserter for.
*/
export async function insertPattern( searchTerm ) {
await searchForPattern( searchTerm );
const insertButton = await page.waitForXPath(
`//div[@role = 'option']//div[contains(text(), '${ searchTerm }')]`
);
await insertButton.click();
await focusSelectedBlock();
// We should wait until the inserter closes and the focus moves to the content.
await waitForInserterCloseAndContentFocus();
}
/**
* Opens the inserter, searches for the given reusable block, then selects the
* first result that appears. It then waits briefly for the block list to
* update.
*
* @param {string} searchTerm The text to search the inserter for.
*/
export async function insertReusableBlock( searchTerm ) {
await searchForReusableBlock( searchTerm );
const insertButton = await page.waitForXPath(
`//button//span[contains(text(), '${ searchTerm }')]`
);
await insertButton.click();
await focusSelectedBlock();
// We should wait until the inserter closes and the focus moves to the content.
await waitForInserterCloseAndContentFocus();
// We should wait until the block is loaded.
await page.waitForXPath(
'//*[contains(@class,"block-library-block__reusable-block-container")]'
);
}
/**
* Opens the inserter, searches for the given block, then selects the
* first result that appears from the block directory. It then waits briefly for the block list to
* update.
*
* @param {string} searchTerm The text to search the inserter for.
*/
export async function insertBlockDirectoryBlock( searchTerm ) {
await searchForBlock( searchTerm );
// Grab the first block in the list.
const insertButton = await page.waitForSelector(
'.block-directory-downloadable-blocks-list button:first-child'
);
await insertButton.click();
await page.waitForFunction(
() =>
! document.body.querySelector(
'.block-directory-downloadable-blocks-list button:first-child.is-busy'
)
);
await focusSelectedBlock();
// We should wait until the inserter closes and the focus moves to the content.
await waitForInserterCloseAndContentFocus();
}