Skip to content

Commit 3b909ac

Browse files
retrofoxtyxla
authored andcommitted
Connectors: Stop e2e capability restriction from leaking across specs (#77857)
* fix cap restriction leak in connectors test plugin Skip map_meta_cap during /wp/v2/plugins REST requests so the e2e cleanup never gets blocked by a leaked restriction, and clear the option on activation as a safety net. * simplify rationale comment * clear connectors capability restriction in e2e cleanup Reset the test restriction option before deactivating the helper plugin so cleanup does not leak blocked plugin capabilities across specs. Made-with: Cursor * update connectors capability e2e fixtures Use controlled connector fixtures for capability assertions so the tests do not depend on the current state of built-in AI providers. Made-with: Cursor
1 parent 6836882 commit 3b909ac

2 files changed

Lines changed: 83 additions & 13 deletions

File tree

packages/e2e-tests/plugins/connectors-capability-restriction.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,59 @@ static function () {
2222
}
2323
);
2424

25+
register_activation_hook(
26+
__FILE__,
27+
static function () {
28+
delete_option( 'gutenberg_test_cap_restriction' );
29+
}
30+
);
31+
2532
register_deactivation_hook(
2633
__FILE__,
2734
static function () {
2835
delete_option( 'gutenberg_test_cap_restriction' );
2936
}
3037
);
3138

39+
add_action(
40+
'wp_connectors_init',
41+
static function ( WP_Connector_Registry $registry ) {
42+
$registry->register(
43+
'test_install_required_connector',
44+
array(
45+
'name' => 'Test Install Required Connector',
46+
'description' => 'A connector backed by a plugin that is not installed.',
47+
'type' => 'ai_provider',
48+
'plugin' => array(
49+
'file' => 'gutenberg-test-connectors-never-installed/plugin.php',
50+
'is_active' => '__return_false',
51+
),
52+
'authentication' => array(
53+
'method' => 'api_key',
54+
'setting_name' => 'gutenberg_test_install_required_connector_api_key',
55+
),
56+
)
57+
);
58+
59+
$registry->register(
60+
'test_activate_required_connector',
61+
array(
62+
'name' => 'Test Activate Required Connector',
63+
'description' => 'A connector backed by an installed inactive plugin.',
64+
'type' => 'ai_provider',
65+
'plugin' => array(
66+
'file' => 'hello/hello.php',
67+
'is_active' => '__return_false',
68+
),
69+
'authentication' => array(
70+
'method' => 'api_key',
71+
'setting_name' => 'gutenberg_test_activate_required_connector_api_key',
72+
),
73+
)
74+
);
75+
}
76+
);
77+
3278
add_filter(
3379
'map_meta_cap',
3480
static function ( $caps, $cap ) {

test/e2e/specs/admin/connectors.spec.js

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ test.describe( 'Connectors', () => {
5353
);
5454
} );
5555

56-
test( 'should display default providers with install buttons', async ( {
56+
test( 'should display default providers with setup buttons', async ( {
5757
page,
5858
admin,
5959
} ) => {
@@ -66,7 +66,7 @@ test.describe( 'Connectors', () => {
6666
} );
6767
await expect( pageTitle ).toBeVisible();
6868

69-
// Verify each connector card shows name as heading, description, and Install button.
69+
// Verify each connector card shows name as heading, description, and Set up button.
7070
for ( const { slug, name, description } of CONNECTORS ) {
7171
const card = page.locator( `.connector-item--${ slug }` );
7272
await expect( card ).toBeVisible();
@@ -86,9 +86,9 @@ test.describe( 'Connectors', () => {
8686
headingId
8787
);
8888

89-
const button = card.getByRole( 'button', { name: 'Install' } );
89+
const button = card.getByRole( 'button', { name: 'Set up' } );
9090
await expect( button ).toBeVisible();
91-
// Install button should not have aria-expanded.
91+
// Set up button should not have aria-expanded until expanded.
9292
await expect( button ).not.toHaveAttribute( 'aria-expanded' );
9393
}
9494

@@ -457,12 +457,36 @@ test.describe( 'Connectors', () => {
457457

458458
test.describe( 'Connectors page capability checks', () => {
459459
const PLUGIN_SLUG = 'gutenberg-test-connectors-capability-restriction';
460+
const installRequiredConnector = {
461+
slug: 'gutenberg-test-connectors-never-installed',
462+
name: 'Test Install Required Connector',
463+
action: 'Install',
464+
};
465+
const activateRequiredConnector = {
466+
slug: 'hello',
467+
name: 'Test Activate Required Connector',
468+
action: 'Activate',
469+
};
470+
const clearCapabilityRestriction = async ( requestUtils ) => {
471+
await requestUtils.rest( {
472+
path: '/wp/v2/settings',
473+
method: 'POST',
474+
data: {
475+
gutenberg_test_cap_restriction: '',
476+
},
477+
} );
478+
};
460479

461480
test.beforeAll( async ( { requestUtils } ) => {
462481
await requestUtils.activatePlugin( PLUGIN_SLUG );
463482
} );
464483

484+
test.afterEach( async ( { requestUtils } ) => {
485+
await clearCapabilityRestriction( requestUtils );
486+
} );
487+
465488
test.afterAll( async ( { requestUtils } ) => {
489+
await clearCapabilityRestriction( requestUtils );
466490
await requestUtils.deactivatePlugin( PLUGIN_SLUG );
467491
} );
468492

@@ -477,7 +501,7 @@ test.describe( 'Connectors', () => {
477501
];
478502

479503
capabilities.forEach( ( [ restriction, label ] ) => {
480-
test( `should show "Not available" when ${ label }`, async ( {
504+
test( `should show unavailable connector actions when ${ label }`, async ( {
481505
page,
482506
admin,
483507
requestUtils,
@@ -495,23 +519,23 @@ test.describe( 'Connectors', () => {
495519
CONNECTORS_PAGE_QUERY
496520
);
497521

498-
// AI plugin callout banner should be hidden when user lacks permissions.
499-
await expect(
500-
page.locator( '.ai-plugin-callout' )
501-
).toBeHidden();
502-
503-
for ( const { slug } of CONNECTORS ) {
522+
for ( const { slug, name, action } of [
523+
installRequiredConnector,
524+
activateRequiredConnector,
525+
] ) {
504526
const card = page.locator( `.connector-item--${ slug }` );
505527
await expect( card ).toBeVisible();
528+
await expect(
529+
card.getByRole( 'heading', { name, level: 2 } )
530+
).toBeVisible();
506531
await expect(
507532
card.getByText( 'Not available' )
508533
).toBeVisible();
509534
await expect(
510-
card.getByRole( 'button', { name: 'Install' } )
535+
card.getByRole( 'button', { name: action } )
511536
).toBeHidden();
512537
}
513538

514-
// Plugin directory link should be hidden.
515539
await expect(
516540
page.getByRole( 'link', {
517541
name: 'search the plugin directory',

0 commit comments

Comments
 (0)