Skip to content

Commit a84b388

Browse files
committed
Update docs and tests
1 parent 324d332 commit a84b388

File tree

11 files changed

+96
-110
lines changed

11 files changed

+96
-110
lines changed

includes/abilities-api/class-wp-ability.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,20 @@ class WP_Ability {
2727
* @var array<string,(bool|string)>
2828
*/
2929
protected static $default_annotations = array(
30-
// An instruction on how to use the ability.
31-
'instruction' => '',
30+
// Instructions on how to use the ability.
31+
'instructions' => '',
3232
// If true, the ability does not modify its environment.
33-
'read_only' => false,
33+
'read_only' => false,
3434
/*
3535
* If true, the ability may perform destructive updates to its environment.
3636
* If false, the ability performs only additive updates.
3737
*/
38-
'destructive' => true,
38+
'destructive' => true,
3939
/*
4040
* If true, calling the ability repeatedly with the same arguments will have no additional effect
4141
* on its environment.
4242
*/
43-
'idempotent' => false,
43+
'idempotent' => false,
4444
);
4545

4646
/**

packages/client/README.md

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ const { getAbilities, getAbility, executeAbility } = wp.abilities;
2828
const abilities = await getAbilities();
2929

3030
// Get a specific ability
31-
const ability = await getAbility('my-plugin/my-ability');
31+
const ability = await getAbility( 'my-plugin/my-ability' );
3232

3333
// Execute an ability
34-
const result = await executeAbility('my-plugin/my-ability', {
34+
const result = await executeAbility( 'my-plugin/my-ability', {
3535
param1: 'value1',
3636
param2: 'value2',
37-
});
37+
} );
3838
```
3939

4040
### Using with React and WordPress Data
@@ -47,24 +47,24 @@ import { store as abilitiesStore } from '@wordpress/abilities';
4747

4848
function MyComponent() {
4949
const abilities = useSelect(
50-
(select) => select(abilitiesStore).getAbilities(),
50+
( select ) => select( abilitiesStore ).getAbilities(),
5151
[]
5252
);
5353

5454
const specificAbility = useSelect(
55-
(select) => select(abilitiesStore).getAbility('my-plugin/my-ability'),
55+
( select ) => select( abilitiesStore ).getAbility( 'my-plugin/my-ability' ),
5656
[]
5757
);
5858

5959
return (
6060
<div>
6161
<h2>All Abilities</h2>
6262
<ul>
63-
{abilities.map((ability) => (
64-
<li key={ability.name}>
65-
<strong>{ability.label}</strong>: {ability.description}
63+
{ abilities.map( ( ability ) => (
64+
<li key={ ability.name }>
65+
<strong>{ ability.label }</strong>: { ability.description }
6666
</li>
67-
))}
67+
) ) }
6868
</ul>
6969
</div>
7070
);
@@ -81,38 +81,38 @@ Returns all registered abilities. Automatically handles pagination to fetch all
8181

8282
```javascript
8383
const abilities = await getAbilities();
84-
console.log(`Found ${abilities.length} abilities`);
84+
console.log( `Found ${ abilities.length } abilities` );
8585
```
8686

8787
#### `getAbility(name: string): Promise<Ability | null>`
8888

8989
Returns a specific ability by name, or null if not found.
9090

9191
```javascript
92-
const ability = await getAbility('my-plugin/create-post');
93-
if (ability) {
94-
console.log(`Found ability: ${ability.label}`);
92+
const ability = await getAbility( 'my-plugin/create-post' );
93+
if ( ability ) {
94+
console.log( `Found ability: ${ ability.label }` );
9595
}
9696
```
9797

9898
#### `executeAbility(name: string, input?: Record<string, any>): Promise<any>`
9999

100-
Executes an ability with optional input parameters. The HTTP method is automatically determined based on the ability's type:
100+
Executes an ability with optional input parameters. The HTTP method is automatically determined based on the ability's annotations:
101101

102-
- `resource` type abilities use GET (read-only operations)
103-
- `tool` type abilities use POST (write operations)
102+
- `read_only` abilities use GET (read-only operations)
103+
- regular abilities use POST (write operations)
104104

105105
```javascript
106-
// Execute a resource ability (GET)
107-
const data = await executeAbility('my-plugin/get-data', {
106+
// Execute a read only ability (GET)
107+
const data = await executeAbility( 'my-plugin/get-data', {
108108
id: 123,
109-
});
109+
} );
110110

111-
// Execute a tool ability (POST)
112-
const result = await executeAbility('my-plugin/create-item', {
111+
// Execute a regular ability (POST)
112+
const result = await executeAbility( 'my-plugin/create-item', {
113113
title: 'New Item',
114114
content: 'Item content',
115-
});
115+
} );
116116
```
117117

118118
### Store Selectors

packages/client/src/__tests__/api.test.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -259,12 +259,12 @@ describe( 'API functions', () => {
259259
).rejects.toThrow( 'invalid input' );
260260
} );
261261

262-
it( 'should execute a resource-type ability via GET', async () => {
262+
it( 'should execute a read only ability via GET', async () => {
263263
const mockAbility: Ability = {
264-
name: 'test/resource',
265-
label: 'Resource Ability',
266-
description: 'Test resource ability',
267-
meta: { type: 'resource' },
264+
name: 'test/read-only',
265+
label: 'Read only Ability',
266+
description: 'Test read only ability.',
267+
annotations: { read_only: true },
268268
input_schema: {
269269
type: 'object',
270270
properties: {
@@ -280,27 +280,27 @@ describe( 'API functions', () => {
280280
getAbility: mockGetAbility,
281281
} );
282282

283-
const mockResponse = { data: 'resource data' };
283+
const mockResponse = { data: 'read only data' };
284284
( apiFetch as unknown as jest.Mock ).mockResolvedValue(
285285
mockResponse
286286
);
287287

288288
const input = { id: '123', format: 'json' };
289-
const result = await executeAbility( 'test/resource', input );
289+
const result = await executeAbility( 'test/read-only', input );
290290

291291
expect( apiFetch ).toHaveBeenCalledWith( {
292-
path: '/wp/v2/abilities/test/resource/run?input%5Bid%5D=123&input%5Bformat%5D=json',
292+
path: '/wp/v2/abilities/test/read-only/run?input%5Bid%5D=123&input%5Bformat%5D=json',
293293
method: 'GET',
294294
} );
295295
expect( result ).toEqual( mockResponse );
296296
} );
297297

298-
it( 'should execute a resource-type ability with empty input', async () => {
298+
it( 'should execute a read only ability with empty input', async () => {
299299
const mockAbility: Ability = {
300-
name: 'test/resource',
301-
label: 'Resource Ability',
302-
description: 'Test resource ability',
303-
meta: { type: 'resource' },
300+
name: 'test/read-only',
301+
label: 'Read only Ability',
302+
description: 'Test read only ability.',
303+
annotations: { read_only: true },
304304
input_schema: { type: 'object' },
305305
output_schema: { type: 'object' },
306306
};
@@ -310,15 +310,15 @@ describe( 'API functions', () => {
310310
getAbility: mockGetAbility,
311311
} );
312312

313-
const mockResponse = { data: 'all resources' };
313+
const mockResponse = { data: 'read only data' };
314314
( apiFetch as unknown as jest.Mock ).mockResolvedValue(
315315
mockResponse
316316
);
317317

318-
const result = await executeAbility( 'test/resource', {} );
318+
const result = await executeAbility( 'test/read-only', {} );
319319

320320
expect( apiFetch ).toHaveBeenCalledWith( {
321-
path: '/wp/v2/abilities/test/resource/run?',
321+
path: '/wp/v2/abilities/test/read-only/run?',
322322
method: 'GET',
323323
} );
324324
expect( result ).toEqual( mockResponse );

packages/client/src/store/__tests__/reducer.test.ts

Lines changed: 6 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -118,46 +118,21 @@ describe( 'Store Reducer', () => {
118118
).not.toHaveProperty( '_embedded' );
119119
} );
120120

121-
it( 'should filter out location property', () => {
122-
const abilities = [
123-
{
124-
name: 'test/ability',
125-
label: 'Test Ability',
126-
description: 'Test ability with location',
127-
location: 'client',
128-
},
129-
];
130-
131-
const action = {
132-
type: RECEIVE_ABILITIES,
133-
abilities,
134-
};
135-
136-
const state = reducer(
137-
{ abilitiesByName: defaultState },
138-
action
139-
);
140-
141-
expect(
142-
state.abilitiesByName[ 'test/ability' ]
143-
).not.toHaveProperty( 'location' );
144-
} );
145-
146121
it( 'should preserve all valid ability properties', () => {
147122
const abilities = [
148123
{
149124
name: 'test/ability',
150125
label: 'Test Ability',
151-
description: 'Full test ability',
126+
description: 'Full test ability.',
152127
input_schema: { type: 'object' },
153128
output_schema: { type: 'object' },
154-
meta: { type: 'resource' as const },
129+
annotations: { read_only: true },
130+
meta: { category: 'test' },
155131
callback: () => Promise.resolve( {} ),
156132
permissionCallback: () => true,
157133
// Extra properties that should be filtered out
158134
_links: { self: { href: '/test' } },
159135
_embedded: { test: 'value' },
160-
location: 'client',
161136
extra_field: 'should be removed',
162137
},
163138
];
@@ -176,17 +151,17 @@ describe( 'Store Reducer', () => {
176151
// Should have valid properties
177152
expect( ability.name ).toBe( 'test/ability' );
178153
expect( ability.label ).toBe( 'Test Ability' );
179-
expect( ability.description ).toBe( 'Full test ability' );
154+
expect( ability.description ).toBe( 'Full test ability.' );
180155
expect( ability.input_schema ).toEqual( { type: 'object' } );
181156
expect( ability.output_schema ).toEqual( { type: 'object' } );
182-
expect( ability.meta ).toEqual( { type: 'resource' } );
157+
expect( ability.annotations ).toEqual( { read_only: true } );
158+
expect( ability.meta ).toEqual( { category: 'test' } );
183159
expect( ability.callback ).toBeDefined();
184160
expect( ability.permissionCallback ).toBeDefined();
185161

186162
// Should NOT have invalid properties
187163
expect( ability ).not.toHaveProperty( '_links' );
188164
expect( ability ).not.toHaveProperty( '_embedded' );
189-
expect( ability ).not.toHaveProperty( 'location' );
190165
expect( ability ).not.toHaveProperty( 'extra_field' );
191166
} );
192167
} );
@@ -225,7 +200,6 @@ describe( 'Store Reducer', () => {
225200
description: 'Test ability',
226201
callback: () => Promise.resolve( {} ),
227202
// Extra properties that should be filtered out
228-
location: 'client',
229203
_links: { self: { href: '/test' } },
230204
extra_field: 'should be removed',
231205
};
@@ -249,7 +223,6 @@ describe( 'Store Reducer', () => {
249223
expect( registeredAbility.callback ).toBeDefined();
250224

251225
// Should NOT have invalid properties
252-
expect( registeredAbility ).not.toHaveProperty( 'location' );
253226
expect( registeredAbility ).not.toHaveProperty( '_links' );
254227
expect( registeredAbility ).not.toHaveProperty( 'extra_field' );
255228
} );

packages/client/src/store/reducer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const ABILITY_KEYS = [
2323
'description',
2424
'input_schema',
2525
'output_schema',
26+
'annotations',
2627
'meta',
2728
'callback',
2829
'permissionCallback',

packages/client/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export interface Ability {
6969
permissionCallback?: PermissionCallback;
7070

7171
/**
72-
* Annotation for the ability.
72+
* Annotations for the ability.
7373
* @see WP_Ability::get_annotations()
7474
*/
7575
annotations?: {

tests/unit/abilities-api/wpAbilitiesRegistry.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ public function set_up(): void {
5959
'permission_callback' => static function (): bool {
6060
return true;
6161
},
62+
'annotations' => array(
63+
'read_only' => true,
64+
),
6265
'meta' => array(
6366
'category' => 'math',
6467
),

tests/unit/abilities-api/wpAbility.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ public function set_up(): void {
2929
'permission_callback' => static function (): bool {
3030
return true;
3131
},
32+
'annotations' => array(
33+
'read_only' => true,
34+
),
3235
'meta' => array(
3336
'category' => 'math',
3437
),

tests/unit/abilities-api/wpRegisterAbility.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ public function set_up(): void {
6060
'permission_callback' => static function (): bool {
6161
return true;
6262
},
63+
'annotations' => array(
64+
'read_only' => true,
65+
),
6366
'meta' => array(
6467
'category' => 'math',
6568
),
@@ -132,6 +135,7 @@ public function test_register_valid_ability(): void {
132135
$this->assertSame( self::$test_ability_args['description'], $result->get_description() );
133136
$this->assertSame( self::$test_ability_args['input_schema'], $result->get_input_schema() );
134137
$this->assertSame( self::$test_ability_args['output_schema'], $result->get_output_schema() );
138+
$this->assertSame( self::$test_ability_args['annotations'], $result->get_annotations() );
135139
$this->assertSame( self::$test_ability_args['meta'], $result->get_meta() );
136140
$this->assertTrue(
137141
$result->check_permissions(

tests/unit/rest-api/wpRestAbilitiesListController.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public function tear_down(): void {
8484
* Register test abilities for testing.
8585
*/
8686
private function register_test_abilities(): void {
87-
// Register a tool ability
87+
// Register a regular ability.
8888
wp_register_ability(
8989
'test/calculator',
9090
array(
@@ -127,7 +127,7 @@ private function register_test_abilities(): void {
127127
)
128128
);
129129

130-
// Register a resource ability
130+
// Register a read only ability.
131131
wp_register_ability(
132132
'test/system-info',
133133
array(
@@ -163,6 +163,9 @@ private function register_test_abilities(): void {
163163
'permission_callback' => static function () {
164164
return current_user_can( 'read' );
165165
},
166+
'annotations' => array(
167+
'read_only' => true,
168+
),
166169
'meta' => array(
167170
'category' => 'system',
168171
),

0 commit comments

Comments
 (0)