Skip to content
Open
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: 18 additions & 1 deletion packages/e2e-tests/plugins/connectors-js-extensibility.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
* Plugin URI: https://github.com/WordPress/gutenberg
* Author: Gutenberg Team
*
* Registers two custom-type connectors on the server:
* Registers three connectors on the server:
*
* 1. test_custom_service — also registered client-side via a script module using
* the merging strategy (two registerConnector calls with the same slug: one
* providing the render function, the other metadata).
* 2. test_server_only_service — server-only, with no client-side render function,
* so it should not display a card in the UI.
* 3. test_api_key_with_custom_render — an api_key connector whose JS render is
* registered *before* the page's `registerDefaultConnectors()` call runs.
* Regression test for the bug where the default ApiKeyConnector overwrote
* third-party custom renders for any api_key-authenticated connector.
*
* @package gutenberg-test-connectors-js-extensibility
*/
Expand Down Expand Up @@ -42,6 +46,19 @@ static function ( WP_Connector_Registry $registry ) {
),
)
);

$registry->register(
'test_api_key_with_custom_render',
array(
'name' => 'Test API Key With Custom Render',
'description' => 'An api_key connector with a JS-registered custom render.',
'type' => 'ai_provider',
'authentication' => array(
'method' => 'api_key',
'settingName' => 'test_api_key_with_custom_render_key',
),
)
);
}
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,27 @@ registerConnector( 'test_custom_service', {
)
),
} );

// Regression test: register a custom render for an api_key-authenticated
// connector. The page's `registerDefaultConnectors()` would otherwise
// overwrite this render with the generic ApiKeyConnector form because the
// store reducer spreads new config over existing entries. The fix in
// `routes/connectors-home/default-connectors.tsx` skips setting
// `args.render = ApiKeyConnector` when an existing render is present.
registerConnector( 'test_api_key_with_custom_render', {
render: ( props ) =>
h(
ConnectorItem,
{
className: 'connector-item--test_api_key_with_custom_render',
name: props.name,
description: props.description,
logo: props.logo,
},
h(
'p',
{ className: 'test-api-key-with-custom-render-content' },
'Custom render survived registerDefaultConnectors().'
)
),
} );
17 changes: 16 additions & 1 deletion routes/connectors-home/default-connectors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@
__experimentalRegisterConnector as registerConnector,
__experimentalConnectorItem as ConnectorItem,
__experimentalDefaultConnectorSettings as DefaultConnectorSettings,
privateApis as connectorsPrivateApis,
type ConnectorConfig,
type ConnectorRenderProps,
} from '@wordpress/connectors';
import { select } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { Badge } from '@wordpress/ui';

/**
* Internal dependencies
*/
import { unlock } from '../lock-unlock';
import { useConnectorPlugin } from './use-connector-plugin';
import {
OpenAILogo,
Expand All @@ -25,6 +28,8 @@
DefaultConnectorLogo,
} from './logos';

const { store: connectorsStore } = unlock( connectorsPrivateApis );

interface ConnectorData {
name: string;
description: string;
Expand Down Expand Up @@ -256,7 +261,17 @@
authentication,
plugin: data.plugin,
};
if ( authentication.method === 'api_key' ) {

// If a third-party plugin's script module already registered a
// custom render for this slug (which can happen when the plugin's
// connector bundle executes before this module's dynamic import
// chain settles), don't overwrite it. The reducer spreads the
// existing entry first, so leaving `render` out of `args` here
// preserves the plugin's render while still merging the
// server-side metadata (logo, plugin install state, etc.).
const existing =

Check failure on line 272 in routes/connectors-home/default-connectors.tsx

View workflow job for this annotation

GitHub Actions / All (Node.js 24 on Linux)

Replace `⏎↹↹↹unlock(·select(·connectorsStore·)·).getConnector(·connectorName·` with `·unlock(·select(·connectorsStore·)·).getConnector(⏎↹↹↹connectorName⏎↹↹`
unlock( select( connectorsStore ) ).getConnector( connectorName );
if ( authentication.method === 'api_key' && ! existing?.render ) {
args.render = ApiKeyConnector;
}

Expand Down
26 changes: 26 additions & 0 deletions test/e2e/specs/admin/connectors.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -581,5 +581,31 @@
card.getByText( 'A custom service for E2E testing.' )
).toBeVisible();
} );

test( 'should preserve a custom render for an api_key connector registered before registerDefaultConnectors', async ( {
page,
admin,
} ) => {
await admin.visitAdminPage(
SETTINGS_PAGE_PATH,
CONNECTORS_PAGE_QUERY
);

const card = page.locator(
'.connector-item--test_api_key_with_custom_render'
);
await expect( card ).toBeVisible();

// The custom render content must be visible — proving the
// JS-supplied render survived registerDefaultConnectors().
await expect(
card.getByText(
'Custom render survived registerDefaultConnectors().'
)
).toBeVisible();

// And the default API key form must NOT be present in this card.
await expect( card.getByLabel( 'API Key' ) ).toHaveCount( 0 );

Check failure on line 608 in test/e2e/specs/admin/connectors.spec.js

View workflow job for this annotation

GitHub Actions / Playwright - 1

[chromium] › specs/admin/connectors.spec.js:585:3 › Connectors › JS extensibility › should preserve a custom render for an api_key connector registered before registerDefaultConnectors

1) [chromium] › specs/admin/connectors.spec.js:585:3 › Connectors › JS extensibility › should preserve a custom render for an api_key connector registered before registerDefaultConnectors Retry #2 ─────────────────────────────────────────────────────────────────────────────────────── Error: expect(locator).toHaveCount(expected) failed Locator: locator('.connector-item--test_api_key_with_custom_render').getByLabel('API Key') Expected: 0 Received: 1 Timeout: 5000ms Call log: - Expect "toHaveCount" with timeout 5000ms - waiting for locator('.connector-item--test_api_key_with_custom_render').getByLabel('API Key') 9 × locator resolved to 1 element - unexpected value "1" 606 | 607 | // And the default API key form must NOT be present in this card. > 608 | await expect( card.getByLabel( 'API Key' ) ).toHaveCount( 0 ); | ^ 609 | } ); 610 | } ); 611 | } ); at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/admin/connectors.spec.js:608:49

Check failure on line 608 in test/e2e/specs/admin/connectors.spec.js

View workflow job for this annotation

GitHub Actions / Playwright - 1

[chromium] › specs/admin/connectors.spec.js:585:3 › Connectors › JS extensibility › should preserve a custom render for an api_key connector registered before registerDefaultConnectors

1) [chromium] › specs/admin/connectors.spec.js:585:3 › Connectors › JS extensibility › should preserve a custom render for an api_key connector registered before registerDefaultConnectors Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── Error: expect(locator).toHaveCount(expected) failed Locator: locator('.connector-item--test_api_key_with_custom_render').getByLabel('API Key') Expected: 0 Received: 1 Timeout: 5000ms Call log: - Expect "toHaveCount" with timeout 5000ms - waiting for locator('.connector-item--test_api_key_with_custom_render').getByLabel('API Key') 9 × locator resolved to 1 element - unexpected value "1" 606 | 607 | // And the default API key form must NOT be present in this card. > 608 | await expect( card.getByLabel( 'API Key' ) ).toHaveCount( 0 ); | ^ 609 | } ); 610 | } ); 611 | } ); at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/admin/connectors.spec.js:608:49

Check failure on line 608 in test/e2e/specs/admin/connectors.spec.js

View workflow job for this annotation

GitHub Actions / Playwright - 1

[chromium] › specs/admin/connectors.spec.js:585:3 › Connectors › JS extensibility › should preserve a custom render for an api_key connector registered before registerDefaultConnectors

1) [chromium] › specs/admin/connectors.spec.js:585:3 › Connectors › JS extensibility › should preserve a custom render for an api_key connector registered before registerDefaultConnectors Error: expect(locator).toHaveCount(expected) failed Locator: locator('.connector-item--test_api_key_with_custom_render').getByLabel('API Key') Expected: 0 Received: 1 Timeout: 5000ms Call log: - Expect "toHaveCount" with timeout 5000ms - waiting for locator('.connector-item--test_api_key_with_custom_render').getByLabel('API Key') 9 × locator resolved to 1 element - unexpected value "1" 606 | 607 | // And the default API key form must NOT be present in this card. > 608 | await expect( card.getByLabel( 'API Key' ) ).toHaveCount( 0 ); | ^ 609 | } ); 610 | } ); 611 | } ); at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/admin/connectors.spec.js:608:49
} );
} );
} );
Loading