This repository has been archived by the owner on Feb 23, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 219
/
utils.js
264 lines (236 loc) · 7.59 KB
/
utils.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
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
/**
* External dependencies
*/
import {
disableSiteEditorWelcomeGuide,
openGlobalBlockInserter,
pressKeyWithModifier,
visitAdminPage,
visitSiteEditor,
} from '@wordpress/e2e-test-utils';
import { WP_ADMIN_DASHBOARD } from '@woocommerce/e2e-utils';
/**
* @typedef {import('@types/puppeteer').Page} Page
* @typedef {import('@types/puppeteer').ElementHandle} ElementHandle
* @typedef {import('@wordpress/blocks').Block} WPBlock
*/
/**
* @typedef {{ addedBy: string, hasActions: boolean, templateTitle: string }} TemplateTableItem
*/
export const DEFAULT_TIMEOUT = 30000;
const SELECTORS = {
canvas: 'iframe[name="editor-canvas"]',
inserter: {
search:
'.components-search-control__input,.block-editor-inserter__search input,.block-editor-inserter__search-input,input.block-editor-inserter__search',
},
templatesListTable: {
actionsContainer: '.edit-site-list-table__actions',
cells: '.edit-site-list-table-column',
headings: 'thead th.edit-site-list-table-column',
root: '.edit-site-list-table',
rows: '.edit-site-list-table-row',
templateTitle: '[data-wp-component="Heading"]',
},
toolbar: {
confirmSave: '.editor-entities-saved-states__save-button',
saveButton: '.edit-site-save-button__button',
savePrompt: '.entities-saved-states__text-prompt',
},
};
/**
* Search for block in the global inserter.
*
* @see https://github.com/WordPress/gutenberg/blob/2356b2d3165acd0af980d52bc93fb1e42748bb25/packages/e2e-test-utils/src/inserter.js#L95
*
* @param {string} searchTerm The text to search the inserter for.
*/
export async function searchForBlock( searchTerm ) {
await page.waitForSelector( SELECTORS.inserter.search );
await page.focus( SELECTORS.inserter.search );
await pressKeyWithModifier( 'primary', 'a' );
await page.keyboard.type( searchTerm );
}
/**
* Opens the inserter, searches for the given term, then selects the first
* result that appears.
*
* @param {string} searchTerm The text to search the inserter for.
*/
export async function insertBlockDontWaitForInsertClose( searchTerm ) {
await openGlobalBlockInserter();
await searchForBlock( searchTerm );
const insertButton = (
await page.$x( `//button//span[text()='${ searchTerm }']` )
)[ 0 ];
await insertButton.click();
}
export const closeInserter = async () => {
if (
await page.evaluate( () => {
return !! document.querySelector(
'.edit-post-header [aria-label="Add block"]'
);
} )
) {
await page.click( '.edit-post-header [aria-label="Add block"]' );
return;
}
await page.click(
'.edit-post-header [aria-label="Toggle block inserter"]'
);
};
const WP_ADMIN_WIDGETS_EDITOR = WP_ADMIN_DASHBOARD + 'widgets.php';
export const openWidgetEditor = async () => {
await page.goto( WP_ADMIN_WIDGETS_EDITOR, {
waitUntil: 'networkidle0',
} );
};
export const closeModalIfExists = async () => {
if (
await page.evaluate( () => {
return !! document.querySelector( '.components-modal__header' );
} )
) {
await page.click(
'.components-modal__header [aria-label="Close dialog"]'
);
}
};
export const openWidgetsEditorBlockInserter = async () => {
await page.click(
'.edit-widgets-header [aria-label="Add block"],.edit-widgets-header [aria-label="Toggle block inserter"]'
);
};
export const isBlockInsertedInWidgetsArea = async ( blockName ) => {
const widgetAreaSelector = '.wp-block-widget-area';
const widgetsArea = await page.$$( widgetAreaSelector );
return widgetsArea.some(
async ( widgetArea ) =>
( await widgetArea.$$( `[data-block-title="${ blockName }"]` )
.length ) > 0
);
};
/**
* Visits the Site Editor main page in Core WordPress
*
* There are two different possible site editor pages:
*
* 1. `themes.php?page=gutenberg-edit-site` is the one used and available if the Gutenberg plugin is enabled.
* 2. `site-editor.php` is the one available in WP Core.
*
* @param {string} query String to be serialized as query portion of URL.
* @param {'core' | 'gutenberg'} [editorContext='core'] Whether to go to the Gutenberg URL or the Core one.
*/
export async function goToSiteEditor( query, editorContext = 'core' ) {
if ( editorContext === 'gutenberg' ) {
await visitSiteEditor( query );
} else {
await visitAdminPage( 'site-editor.php', query );
await disableSiteEditorWelcomeGuide();
}
}
/**
* Waits for the Gutenberg canvas to be available
*
* @param {number} [timeout=DEFAULT_TIMEOUT] The amount of ms to wait for the element
*/
export async function waitForCanvas( timeout = DEFAULT_TIMEOUT ) {
await page.waitForSelector( SELECTORS.canvas, { timeout } );
}
/**
* Gets the text value of an element
*
* If the element is an `input` it will get the `value`, otherwise,
* it will get the `textContent`.
*
* @param {string} selector The selector for the desired element
* @param {Page | ElementHandle} [root=page] The root from which to search for the selector
*
* @return {Promise<string[]>} An array of text contained in those selected elements
*/
export async function getTextContent( selector, root = page ) {
return root.$$eval( selector, ( $elements ) => {
return $elements.map(
( $element ) => $element.value || $element.textContent
);
} );
}
/**
* Checks whether an element exists under a certain context
*
* @param {string} selector The selector for the desired element
* @param {Page | ElementHandle} [root=page] The root from which to search for the selector
*
* @return {Promise<boolean>} Whether the element exists or not
*/
export async function elementExists( selector, root = page ) {
return !! ( await root.$( selector ) );
}
/**
* Saves a template
*/
export async function saveTemplate() {
const { confirmSave, saveButton, savePrompt } = SELECTORS.toolbar;
await page.click( saveButton );
await page.waitForSelector( savePrompt );
await page.click( confirmSave );
await page.waitForSelector( `${ saveButton }[aria-disabled="true"]` );
}
/**
* Gets all available templates from the template list table UI
*
* @return {Promise<TemplateTableItem[]>} A promise of an array of informations about the templates extracted from the UI
*/
export async function getAllTemplates() {
const { templatesListTable } = SELECTORS;
await page.waitForSelector( templatesListTable.root );
const table = await page.$( templatesListTable.root );
if ( ! table ) throw new Error( 'Templates table not found' );
const rows = await table.$$( templatesListTable.rows );
return Promise.all(
rows.map( async ( row ) => ( {
addedBy: (
await getTextContent( templatesListTable.cells, row )
)[ 1 ],
hasActions: await elementExists(
templatesListTable.actionsContainer,
row
),
templateTitle: (
await getTextContent( templatesListTable.templateTitle, row )
)[ 0 ],
} ) )
);
}
/**
* Gets all the blocks that fulfill a given predicate
*
* @param {( block: WPBlock ) => boolean} predicate The function invoked per iteration
* @return {Promise< Partial< WPBlock >[] >} The blocks which have been found
*/
export async function filterCurrentBlocks( predicate ) {
/**
* @type {WPBlock[]}
*/
const blocks = await page.evaluate( () => {
/**
* Gets all serializeable data from a block
*
* @param {WPBlock} block A Gutenberg Block
* @return {Partial<WPBlock>} A block with unserializeable values turned to `null`
*/
function getSerializeableBlockData( block ) {
return JSON.parse( JSON.stringify( block ) );
}
const blockEditorStore = window.wp.data.select( 'core/block-editor' );
/**
* @type {string[]}
*/
const allClientIds = blockEditorStore.getClientIdsWithDescendants();
return allClientIds.map( ( id ) =>
getSerializeableBlockData( blockEditorStore.getBlock( id ) )
);
} );
return blocks.filter( predicate );
}