-
Notifications
You must be signed in to change notification settings - Fork 5
/
block-directory.test.js
260 lines (210 loc) · 7.36 KB
/
block-directory.test.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
/**
* External dependencies
*/
const fs = require('fs').promises;
const core = require( '@actions/core' );
const github = require( '@actions/github' );
const promiseAny = require( 'promise.any' );
promiseAny.shim();
/**
* WordPress dependencies
*/
import {
createNewPost,
searchForBlock,
deactivatePlugin,
uninstallPlugin,
} from '@wordpress/e2e-test-utils';
/**
* Internal dependencies
*/
import {
getThirdPartyBlocks,
expectWithMessage,
removeAllBlocks,
getAllLoadedScripts,
getAllLoadedStyles,
} from './utils';
import {
wporgHttpCallback,
setOutput,
} from './utils/wporg-callback';
import { waitUntilNetworkIdle } from './utils/network-idle';
// Filter browser requests.
// - Ensure that wp-content/*.(css|js) always 404's instead of matching WordPress.
// - favicons are not needed.
require( './utils/filter-requests' );
// We don't want to see warnings during these tests
console.warn = () => {};
// Depending on the environment, the url may be encoded or not.
const urlMatch = ( url ) => {
const urlPart = '/wp/v2/block-directory/search';
const encoded = encodeURIComponent( urlPart );
return url.indexOf( urlPart ) >= 0 || url.indexOf( encoded ) >= 0;
};
const payload = github.context.payload.client_payload || {};
const pluginSlug = process.env.PLUGIN_SLUG || payload.slug;
const searchTerm = `slug:${ pluginSlug }`;
// Variable to hold any encounted JS errors.
let jsError = false;
page.on( 'pageerror', ( error ) => {
jsError = error.toString();
console.log( error );
} );
// Track the last 404 response
let lastFourOhFour = false;
page.on('response', ( response ) => {
const url = response.url()
.replace(
/^http:\/\/[^/]+\/(wp-content\/plugins\/[^/]+\/)/,
''
)
.replace( /[?&]ver=[a-z0-9.-]+/, '' );
if ( 404 === response.status() ) {
lastFourOhFour = url;
}
} );
core.info( `
--------------------------------------------------------------
Running Tests for "${ pluginSlug }"
--------------------------------------------------------------
` );
// Send the URL to this actions run
if ( process.env.GITHUB_RUN_ID ) {
setOutput( 'lastRunURL', `https://github.com/${ process.env.GITHUB_REPOSITORY }/actions/runs/${ process.env.GITHUB_RUN_ID }` );
}
describe( `Block Directory Tests`, () => {
beforeEach( async () => {
await createNewPost();
await removeAllBlocks();
jsError = false;
} );
afterAll( async () => {
await wporgHttpCallback( pluginSlug );
await deactivatePlugin( pluginSlug );
await uninstallPlugin( pluginSlug );
} );
// Be patient.
page.setDefaultTimeout( 60000 );
let freshScripts = [];
let freshStyles = [];
it( 'Block returns from API and installs', async () => {
try {
// Determine the loaded assets, store it for the next test.
freshScripts = await getAllLoadedScripts();
freshStyles = await getAllLoadedStyles();
await searchForBlock( searchTerm );
const finalResponse = await page.waitForResponse(
( response ) =>
urlMatch( response.url() ) &&
response.status() === 200 &&
response.request().method() === 'GET' // We don't want the OPTIONS request
);
const resp = await finalResponse.json();
await expectWithMessage( () => {
expect( Array.isArray( resp ) ).toBeTruthy();
}, `The search result for "${ pluginSlug }" isn't an array.` );
await expectWithMessage( () => {
expect( resp.length ).toBeGreaterThan( 0 );
}, `We found no matching blocks for "${ pluginSlug }" in the directory.` );
const addBtnSelector =
'.block-directory-downloadable-blocks-list button:first-child';
await page.waitForSelector( addBtnSelector );
// Output a screenshot of the Search Results for debugging.
await (
await page.$(
'.block-directory-downloadable-blocks-list button:first-child'
)
).screenshot( { path: 'screenshots/searchResults.png' } );
setOutput( 'screenshotSearchResults', 'file:screenshots/searchResults.png' );
// Add the block
await page.click( addBtnSelector );
// Watch the button go busy…
await page.waitForSelector( addBtnSelector + '.is-busy' );
// Then either non-busy or removed.
await Promise.any( [
// This is the expected case, the inserter switched back to block-types-list.
page.waitForSelector(
'button.block-editor-block-types-list-item'
),
// But in some cases the inserted block has a restricted set of "children",
// which interacts with the filter & Block Directory, so the add button
// doesn't go away, it just becomes "un-busy".
// See https://github.com/WordPress/gutenberg/pull/24148
page.waitForSelector( addBtnSelector + ':not(.is-busy)' ),
] );
// And wait for the Network to go idle (Assets inserted)
await waitUntilNetworkIdle( 'networkidle0' );
// Check to see if there was a specific reason for a failure.
let error = await page.evaluate( () => {
const el = document.querySelector(
'.block-directory-downloadable-block-notice.is-error .block-directory-downloadable-block-notice__content'
);
return el ? el.innerText : false;
} );
if ( error && 'Error loading asset.' === error && lastFourOhFour ) {
// Alter the error slightly.
error = `Error loading asset "${ lastFourOhFour }"`;
}
await expectWithMessage( () => {
expect( error ).toBeFalsy();
}, `Couldn't install "${ pluginSlug }"; '${ error }'` );
const blocks = await getThirdPartyBlocks();
await expectWithMessage( () => {
expect( blocks.length ).toBeGreaterThan( 0 );
}, `Couldn't install "${ pluginSlug }". No registered blocks detected.` );
// check to see if it errored.
await expectWithMessage( () => {
expect( jsError ).toBeFalsy();
}, `Javascript error: ${ jsError }` );
// wait for the element to exist in the editor
await expectWithMessage( async function () {
await page.waitForSelector(
`div[data-type="${ blocks[ 0 ].name }"]`
)
},
`Expected block "${ blocks[ 0 ].name }" not added to the document after install.`
);
// Get a screenshot of the block.
try {
await (
await page.waitForSelector(
'.is-root-container .wp-block:not([data-type^="core/"])'
)
).screenshot( { path: 'screenshots/block.png' } );
setOutput( 'screenshotBlock', 'file:screenshots/block.png' );
} catch ( e ) {
// Ignore any error here, the test should still succeed.
}
setOutput( 'error', '' );
setOutput( 'success', true );
} catch ( e ) {
core.setFailed( e.message );
setOutput( 'error', jsError || e.message );
setOutput( 'success', false );
throw e;
}
} );
it( 'Block Installed - Extract Scripts & Styles required', async () => {
// Page reloaded from previous test.
await expectWithMessage( () => {
expect( freshScripts.length ).toBeGreaterThan( 0 );
expect( freshStyles.length ).toBeGreaterThan( 0 );
}, `The previous test did not load scripts/styles.`, false );
const blocks = await getThirdPartyBlocks();
await expectWithMessage( () => {
expect( blocks.length ).toBeGreaterThan( 0 );
}, `Block not installed.`, false );
const loadedScripts = await getAllLoadedScripts();
const loadedStyles = await getAllLoadedStyles();
const scriptDiff = loadedScripts.filter(
( x ) => ! freshScripts.some( ( y ) => x.id === y.id )
);
const styleDiff = loadedStyles.filter(
( x ) => ! freshStyles.some( ( y ) => x.id === y.id )
);
setOutput( 'scripts', scriptDiff );
setOutput( 'styles', styleDiff );
setOutput( 'blocks', blocks );
} );
} );