Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions packages/e2e-tests/plugins/connectors-empty-state.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php
/**
* Plugin Name: Gutenberg Test Connectors Empty State
* Plugin URI: https://github.com/WordPress/gutenberg
* Author: Gutenberg Team
*
* Removes the default connector data so the Connectors page renders its empty state.
*
* @package gutenberg-test-connectors-empty-state
*/

// Remove the Gutenberg filter that provides default connector data.
add_action(
'init',
static function () {
remove_filter( 'script_module_data_options-connectors-wp-admin', '_gutenberg_get_connector_script_module_data' );
},
PHP_INT_MAX
);
67 changes: 50 additions & 17 deletions routes/connectors-home/stage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
* WordPress dependencies
*/
import { Page } from '@wordpress/admin-ui';
import { __experimentalVStack as VStack } from '@wordpress/components';
import {
Button,
__experimentalHeading as Heading,
__experimentalText as Text,
__experimentalVStack as VStack,
} from '@wordpress/components';
import {
privateApis as connectorsPrivateApis,
type ConnectorConfig,
Expand Down Expand Up @@ -36,29 +41,57 @@ function ConnectorsPage() {
[]
);

const isEmpty = connectors.length === 0;

return (
<Page
title={ __( 'Connectors' ) }
subTitle={ __(
'All of your API keys and credentials are stored here and shared across plugins. Configure once and use everywhere.'
) }
>
<div className="connectors-page">
<VStack spacing={ 3 }>
{ connectors.map( ( connector: ConnectorConfig ) => {
if ( connector.render ) {
return (
<connector.render
key={ connector.slug }
slug={ connector.slug }
label={ connector.label }
description={ connector.description }
/>
);
}
return null;
} ) }
</VStack>
<div
className={ `connectors-page${
isEmpty ? ' connectors-page--empty' : ''
}` }
>
{ isEmpty ? (
<VStack
alignment="center"
spacing={ 3 }
style={ { maxWidth: 480 } }
>
<VStack alignment="center" spacing={ 2 }>
<Heading level={ 2 } size={ 15 } weight={ 600 }>
{ __( 'No connectors yet' ) }
</Heading>
<Text size={ 12 }>
{ __(
'Connectors appear here when you install plugins that use external services. Each plugin registers the API keys it needs, and you manage them all in one place.'
) }
</Text>
</VStack>
<Button variant="secondary" href="plugin-install.php">
{ __( 'Learn more' ) }
</Button>
</VStack>
) : (
<VStack spacing={ 3 }>
{ connectors.map( ( connector: ConnectorConfig ) => {
if ( connector.render ) {
return (
<connector.render
key={ connector.slug }
slug={ connector.slug }
label={ connector.label }
description={ connector.description }
/>
);
}
return null;
} ) }
</VStack>
) }
{ canInstallPlugins && (
<p>
{ createInterpolateElement(
Expand Down
10 changes: 10 additions & 0 deletions routes/connectors-home/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@
font-family: monospace;
}

&--empty {
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 32px;
text-align: center;
}

> p {
text-align: center;
color: $gray-600;
Expand Down
51 changes: 51 additions & 0 deletions test/e2e/specs/admin/connectors.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,57 @@ test.describe( 'Connectors', () => {
).toHaveAttribute( 'href', 'plugin-install.php' );
} );

test.describe( 'Empty state', () => {
const PLUGIN_SLUG = 'gutenberg-test-connectors-empty-state';

test.beforeAll( async ( { requestUtils } ) => {
await requestUtils.activatePlugin( PLUGIN_SLUG );
} );

test.afterAll( async ( { requestUtils } ) => {
await requestUtils.deactivatePlugin( PLUGIN_SLUG );
} );

test( 'should display an empty state when no connectors are registered', async ( {
page,
admin,
} ) => {
await admin.visitAdminPage(
SETTINGS_PAGE_PATH,
CONNECTORS_PAGE_QUERY
);

// Verify the empty state heading is visible.
await expect(
page.getByRole( 'heading', { name: 'No connectors yet' } )
).toBeVisible();

// Verify the explanatory description is visible.
await expect(
page.getByText(
'Connectors appear here when you install plugins that use external services.'
)
).toBeVisible();

// Verify the "Learn more" button links to plugin directory.
const learnMoreButton = page.getByRole( 'link', {
name: 'Learn more',
} );
await expect( learnMoreButton ).toBeVisible();
await expect( learnMoreButton ).toHaveAttribute(
'href',
'plugin-install.php'
);

// Verify none of the default connector cards are shown.
for ( const { slug } of CONNECTORS ) {
await expect(
page.locator( `.connector-item--${ slug }` )
).toBeHidden();
}
} );
} );

test.describe( 'Connectors page capability checks', () => {
const PLUGIN_SLUG = 'gutenberg-test-connectors-capability-restriction';

Expand Down
Loading