diff --git a/lib/compat.php b/lib/compat.php
index 008298df270967..df1277c459f0e5 100644
--- a/lib/compat.php
+++ b/lib/compat.php
@@ -267,3 +267,18 @@ function gutenberg_override_reusable_block_post_type_labels() {
);
}
add_filter( 'post_type_labels_wp_block', 'gutenberg_override_reusable_block_post_type_labels', 10, 0 );
+
+/**
+ * Update allowed inline style attributes list.
+ *
+ * Note: This should be removed when the minimum required WP version is >= 5.8.
+ *
+ * @param string[] $attrs Array of allowed CSS attributes.
+ * @return string[] CSS attributes.
+ */
+function gutenberg_safe_style_attrs( $attrs ) {
+ $attrs[] = 'object-position';
+
+ return $attrs;
+}
+add_filter( 'safe_style_css', 'gutenberg_safe_style_attrs' );
diff --git a/packages/block-editor/src/components/block-list/insertion-point.js b/packages/block-editor/src/components/block-list/insertion-point.js
index db2653b031bc7e..bbb3be4570fe0f 100644
--- a/packages/block-editor/src/components/block-list/insertion-point.js
+++ b/packages/block-editor/src/components/block-list/insertion-point.js
@@ -199,6 +199,18 @@ function InsertionPointPopover( {
}
}
+ // Only show the inserter when there's a `nextElement` (a block after the
+ // insertion point). At the end of the block list the trailing appender
+ // should serve the purpose of inserting blocks.
+ const showInsertionPointInserter =
+ ! isHidden && nextElement && ( isInserterShown || isInserterForced );
+
+ // Show the indicator if the insertion point inserter is visible, or if
+ // the `showInsertionPoint` state is `true`. The latter is generally true
+ // when hovering blocks for insertion in the block library.
+ const showInsertionPointIndicator =
+ showInsertionPointInserter || ( ! isHidden && showInsertionPoint );
+
/* eslint-disable jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */
// While ideally it would be enough to capture the
// bubbling focus event from the Inserter, due to the
@@ -223,13 +235,10 @@ function InsertionPointPopover( {
className={ className }
style={ style }
>
- { ! isHidden &&
- ( showInsertionPoint ||
- isInserterShown ||
- isInserterForced ) && (
-
- ) }
- { ! isHidden && ( isInserterShown || isInserterForced ) && (
+ { showInsertionPointIndicator && (
+
+ ) }
+ { showInsertionPointInserter && (
0 && (
{
await navigationPanel.clickItemByText( 'Index' );
await navigationPanel.close();
- // Click the first block so that the template part inserts in the right place.
- const firstBlock = await canvas().$( '.wp-block' );
- await firstBlock.click();
+ // Select the header template part via list view.
+ await page.click( 'button[aria-label="List View"]' );
+ const headerTemplatePartListViewButton = await page.waitForXPath(
+ '//button[contains(@class, "block-editor-block-navigation-block-select-button")][contains(., "Header")]'
+ );
+ headerTemplatePartListViewButton.click();
+ await page.click( 'button[aria-label="Close list view sidebar"]' );
// Insert something to dirty the editor.
await insertBlock( 'Paragraph' );
diff --git a/packages/env/lib/build-docker-compose-config.js b/packages/env/lib/build-docker-compose-config.js
index 668836de88878e..b17cb7bb58212e 100644
--- a/packages/env/lib/build-docker-compose-config.js
+++ b/packages/env/lib/build-docker-compose-config.js
@@ -9,6 +9,7 @@ const path = require( 'path' );
* Internal dependencies
*/
const { hasSameCoreSource } = require( './wordpress' );
+const { dbEnv } = require( './config' );
/**
* @typedef {import('./config').WPConfig} WPConfig
@@ -176,26 +177,40 @@ module.exports = function buildDockerComposeConfig( config ) {
image: 'mariadb',
ports: [ '3306' ],
environment: {
- MYSQL_ALLOW_EMPTY_PASSWORD: 'yes',
+ MYSQL_ROOT_PASSWORD:
+ dbEnv.credentials.WORDPRESS_DB_PASSWORD,
+ MYSQL_DATABASE: dbEnv.development.WORDPRESS_DB_NAME,
},
volumes: [ 'mysql:/var/lib/mysql' ],
},
+ 'tests-mysql': {
+ image: 'mariadb',
+ ports: [ '3306' ],
+ environment: {
+ MYSQL_ROOT_PASSWORD:
+ dbEnv.credentials.WORDPRESS_DB_PASSWORD,
+ MYSQL_DATABASE: dbEnv.tests.WORDPRESS_DB_NAME,
+ },
+ volumes: [ 'mysql-test:/var/lib/mysql' ],
+ },
wordpress: {
build: '.',
depends_on: [ 'mysql' ],
image: developmentWpImage,
ports: [ developmentPorts ],
environment: {
- WORDPRESS_DB_NAME: 'wordpress',
+ ...dbEnv.credentials,
+ ...dbEnv.development,
},
volumes: developmentMounts,
},
'tests-wordpress': {
- depends_on: [ 'mysql' ],
+ depends_on: [ 'tests-mysql' ],
image: testsWpImage,
ports: [ testsPorts ],
environment: {
- WORDPRESS_DB_NAME: 'tests-wordpress',
+ ...dbEnv.credentials,
+ ...dbEnv.tests,
},
volumes: testsMounts,
},
@@ -204,12 +219,20 @@ module.exports = function buildDockerComposeConfig( config ) {
image: developmentWpCliImage,
volumes: developmentMounts,
user: cliUser,
+ environment: {
+ ...dbEnv.credentials,
+ ...dbEnv.development,
+ },
},
'tests-cli': {
depends_on: [ 'tests-wordpress' ],
image: testsWpCliImage,
volumes: testsMounts,
user: cliUser,
+ environment: {
+ ...dbEnv.credentials,
+ ...dbEnv.tests,
+ },
},
composer: {
image: 'composer',
@@ -228,6 +251,8 @@ module.exports = function buildDockerComposeConfig( config ) {
LOCAL_DIR: 'html',
WP_PHPUNIT__TESTS_CONFIG:
'/var/www/html/phpunit-wp-config.php',
+ ...dbEnv.credentials,
+ ...dbEnv.tests,
},
},
},
@@ -235,6 +260,7 @@ module.exports = function buildDockerComposeConfig( config ) {
...( ! config.coreSource && { wordpress: {} } ),
...( ! config.coreSource && { 'tests-wordpress': {} } ),
mysql: {},
+ 'mysql-test': {},
'phpunit-uploads': {},
},
};
diff --git a/packages/env/lib/commands/start.js b/packages/env/lib/commands/start.js
index 22fe075948c4a0..4f3a00cc927dd7 100644
--- a/packages/env/lib/commands/start.js
+++ b/packages/env/lib/commands/start.js
@@ -24,6 +24,7 @@ const downloadSources = require( '../download-sources' );
const {
checkDatabaseConnection,
makeContentDirectoriesWritable,
+ makeConfigWritable,
configureWordPress,
setupWordPressDirectories,
} = require( '../wordpress' );
@@ -140,6 +141,11 @@ module.exports = async function start( { spinner, debug, update, xdebug } ) {
: [],
} );
+ await Promise.all( [
+ makeConfigWritable( 'development', config ),
+ makeConfigWritable( 'tests', config ),
+ ] );
+
// Only run WordPress install/configuration when config has changed.
if ( shouldConfigureWp ) {
spinner.text = 'Configuring WordPress.';
diff --git a/packages/env/lib/config/db-env.js b/packages/env/lib/config/db-env.js
new file mode 100644
index 00000000000000..6f06ff97315106
--- /dev/null
+++ b/packages/env/lib/config/db-env.js
@@ -0,0 +1,23 @@
+// Username and password used in all databases
+const credentials = {
+ WORDPRESS_DB_USER: 'root',
+ WORDPRESS_DB_PASSWORD: 'password',
+};
+
+// Environment for test database
+const tests = {
+ WORDPRESS_DB_NAME: 'tests-wordpress',
+ WORDPRESS_DB_HOST: 'tests-mysql',
+};
+
+// Environment for development database. DB host gets default value which is set
+// elsewhere
+const development = {
+ WORDPRESS_DB_NAME: 'wordpress',
+};
+
+module.exports = {
+ credentials,
+ tests,
+ development,
+};
diff --git a/packages/env/lib/config/index.js b/packages/env/lib/config/index.js
index 0dbbcc08a5b8ac..1a944f43501d0d 100644
--- a/packages/env/lib/config/index.js
+++ b/packages/env/lib/config/index.js
@@ -3,6 +3,7 @@
*/
const readConfig = require( './config' );
const { ValidationError } = require( './validate-config' );
+const dbEnv = require( './db-env' );
/**
* @typedef {import('./config').WPConfig} WPConfig
@@ -13,4 +14,5 @@ const { ValidationError } = require( './validate-config' );
module.exports = {
ValidationError,
readConfig,
+ dbEnv,
};
diff --git a/packages/env/lib/wordpress.js b/packages/env/lib/wordpress.js
index 07705167ac1dc4..da632f9703b5b6 100644
--- a/packages/env/lib/wordpress.js
+++ b/packages/env/lib/wordpress.js
@@ -47,6 +47,27 @@ async function makeContentDirectoriesWritable(
);
}
+/**
+ * Makes wp-config.php owned by www-data so that WordPress can work with the
+ * file.
+ *
+ * @param {WPEnvironment} environment The environment to check. Either 'development' or 'tests'.
+ * @param {WPConfig} config The wp-env config object.
+ */
+async function makeConfigWritable(
+ environment,
+ { dockerComposeConfigPath, debug }
+) {
+ await dockerCompose.exec(
+ environment === 'development' ? 'wordpress' : 'tests-wordpress',
+ 'chown www-data:www-data wp-config.php',
+ {
+ config: dockerComposeConfigPath,
+ log: debug,
+ }
+ );
+}
+
/**
* Checks a WordPress database connection. An error is thrown if the test is
* unsuccessful.
@@ -260,6 +281,7 @@ async function copyCoreFiles( fromPath, toPath ) {
module.exports = {
hasSameCoreSource,
makeContentDirectoriesWritable,
+ makeConfigWritable,
checkDatabaseConnection,
configureWordPress,
resetDatabase,