Skip to content

Commit 1e273c3

Browse files
committed
fix: increase test coverage
1 parent 05f4cca commit 1e273c3

File tree

7 files changed

+368
-47
lines changed

7 files changed

+368
-47
lines changed

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -537,9 +537,7 @@ describe( 'API functions', () => {
537537
} );
538538

539539
it( 'should return empty array when no categories exist', async () => {
540-
const mockGetAbilityCategories = jest
541-
.fn()
542-
.mockResolvedValue( [] );
540+
const mockGetAbilityCategories = jest.fn().mockResolvedValue( [] );
543541
( resolveSelect as jest.Mock ).mockReturnValue( {
544542
getAbilityCategories: mockGetAbilityCategories,
545543
} );
@@ -575,9 +573,7 @@ describe( 'API functions', () => {
575573
} );
576574

577575
it( 'should return null if category not found', async () => {
578-
const mockGetAbilityCategory = jest
579-
.fn()
580-
.mockResolvedValue( null );
576+
const mockGetAbilityCategory = jest.fn().mockResolvedValue( null );
581577
( resolveSelect as jest.Mock ).mockReturnValue( {
582578
getAbilityCategory: mockGetAbilityCategory,
583579
} );

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

Lines changed: 103 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
* Tests for store actions.
33
*/
44

5+
/**
6+
* WordPress dependencies
7+
*/
8+
import { resolveSelect } from '@wordpress/data';
9+
510
/**
611
* Internal dependencies
712
*/
@@ -17,6 +22,11 @@ import {
1722
} from '../constants';
1823
import type { Ability } from '../../types';
1924

25+
// Mock the WordPress data store
26+
jest.mock( '@wordpress/data', () => ( {
27+
resolveSelect: jest.fn(),
28+
} ) );
29+
2030
describe( 'Store Actions', () => {
2131
describe( 'receiveAbilities', () => {
2232
it( 'should create an action to receive abilities', () => {
@@ -224,7 +234,9 @@ describe( 'Store Actions', () => {
224234

225235
await expect(
226236
action( { select: mockSelect, dispatch: mockDispatch } )
227-
).rejects.toThrow( 'Ability "test/ability" must have a description' );
237+
).rejects.toThrow(
238+
'Ability "test/ability" must have a description'
239+
);
228240
expect( mockDispatch ).not.toHaveBeenCalled();
229241
} );
230242

@@ -294,19 +306,23 @@ describe( 'Store Actions', () => {
294306
callback: jest.fn(),
295307
};
296308

297-
// Update mock to include this category
298-
mockSelect.getAbilityCategory.mockImplementation(
299-
( slug: string ) => {
300-
if ( slug === validCategory || slug === 'test-category' || slug === 'data-retrieval' ) {
301-
return {
302-
slug,
303-
label: 'Test',
304-
description: 'Test',
305-
};
306-
}
307-
return null;
308-
}
309-
);
309+
mockSelect.getAbilityCategories.mockReturnValue( [
310+
{
311+
slug: 'test-category',
312+
label: 'Test Category',
313+
description: 'Test category for testing',
314+
},
315+
{
316+
slug: 'data-retrieval',
317+
label: 'Data Retrieval',
318+
description: 'Abilities that retrieve data',
319+
},
320+
{
321+
slug: validCategory,
322+
label: 'Test Category',
323+
description: 'Test',
324+
},
325+
] );
310326

311327
mockSelect.getAbility.mockReturnValue( null );
312328
mockDispatch.mockClear();
@@ -322,8 +338,18 @@ describe( 'Store Actions', () => {
322338
} );
323339

324340
it( 'should validate and reject ability with non-existent category', async () => {
325-
// Override getAbilityCategory to only return null
326-
mockSelect.getAbilityCategory.mockReturnValue( null );
341+
mockSelect.getAbilityCategories.mockReturnValue( [
342+
{
343+
slug: 'test-category',
344+
label: 'Test Category',
345+
description: 'Test category for testing',
346+
},
347+
{
348+
slug: 'data-retrieval',
349+
label: 'Data Retrieval',
350+
description: 'Abilities that retrieve data',
351+
},
352+
] );
327353

328354
const ability: Ability = {
329355
name: 'test/ability',
@@ -344,11 +370,18 @@ describe( 'Store Actions', () => {
344370
} );
345371

346372
it( 'should accept ability with existing category', async () => {
347-
mockSelect.getAbilityCategory.mockReturnValue( {
348-
slug: 'data-retrieval',
349-
label: 'Data Retrieval',
350-
description: 'Abilities that retrieve data',
351-
} );
373+
mockSelect.getAbilityCategories.mockReturnValue( [
374+
{
375+
slug: 'test-category',
376+
label: 'Test Category',
377+
description: 'Test category for testing',
378+
},
379+
{
380+
slug: 'data-retrieval',
381+
label: 'Data Retrieval',
382+
description: 'Abilities that retrieve data',
383+
},
384+
] );
352385

353386
const ability: Ability = {
354387
name: 'test/ability',
@@ -361,9 +394,8 @@ describe( 'Store Actions', () => {
361394
const action = registerAbility( ability );
362395
await action( { select: mockSelect, dispatch: mockDispatch } );
363396

364-
expect( mockSelect.getAbilityCategory ).toHaveBeenCalledWith(
365-
'data-retrieval'
366-
);
397+
// We check the categories array now, not calling getAbilityCategory
398+
expect( mockSelect.getAbilityCategories ).toHaveBeenCalled();
367399
expect( mockDispatch ).toHaveBeenCalledWith( {
368400
type: REGISTER_ABILITY,
369401
ability,
@@ -414,6 +446,53 @@ describe( 'Store Actions', () => {
414446
).rejects.toThrow( 'Ability "test/ability" is already registered' );
415447
expect( mockDispatch ).not.toHaveBeenCalled();
416448
} );
449+
450+
it( 'should load categories when store is empty before validation', async () => {
451+
// First call returns empty, second call returns loaded categories
452+
let callCount = 0;
453+
mockSelect.getAbilityCategories.mockImplementation( () => {
454+
callCount++;
455+
if ( callCount === 1 ) {
456+
return []; // Empty on first call
457+
}
458+
return [
459+
{
460+
slug: 'test-category',
461+
label: 'Test Category',
462+
description: 'Test category',
463+
},
464+
]; // Loaded on second call
465+
} );
466+
467+
// Mock resolveSelect to return a mock that resolves the getAbilityCategories call
468+
const mockResolveSelectFn = jest.fn().mockReturnValue( {
469+
getAbilityCategories: jest.fn().mockResolvedValue( undefined ),
470+
} );
471+
( resolveSelect as jest.Mock ).mockImplementation(
472+
mockResolveSelectFn
473+
);
474+
475+
const ability: Ability = {
476+
name: 'test/ability',
477+
label: 'Test Ability',
478+
description: 'Test description',
479+
category: 'test-category',
480+
callback: jest.fn(),
481+
};
482+
483+
const action = registerAbility( ability );
484+
await action( { select: mockSelect, dispatch: mockDispatch } );
485+
486+
// Should have called getAbilityCategories twice (once to check, once after loading)
487+
expect( mockSelect.getAbilityCategories ).toHaveBeenCalledTimes(
488+
2
489+
);
490+
// Should have successfully registered
491+
expect( mockDispatch ).toHaveBeenCalledWith( {
492+
type: REGISTER_ABILITY,
493+
ability,
494+
} );
495+
} );
417496
} );
418497

419498
describe( 'unregisterAbility', () => {

0 commit comments

Comments
 (0)