Add coexistence checks to all enqueue methods to prevent loading both React and Grid.js assets simultaneously. Changes: - ReactAdmin.php: Only enqueue React assets when ?react=1 - Init.php: Skip Grid.js when React active on admin pages - Form.php, Coupon.php, Access.php: Restore classic assets when ?react=0 - Customer.php, Product.php, License.php: Add coexistence checks Now the toggle between Classic and React versions works correctly. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
174 lines
4.4 KiB
JavaScript
174 lines
4.4 KiB
JavaScript
/**
|
|
* Internal dependencies
|
|
*/
|
|
import { createRegistry, controls } from '..';
|
|
|
|
describe( 'controls', () => {
|
|
// Create a registry with store to test select controls.
|
|
function createSelectTestRegistry() {
|
|
const registry = createRegistry();
|
|
|
|
// State is initially null and can receive data.
|
|
// Typical for fetching data from remote locations.
|
|
const reducer = ( state = null, action ) => {
|
|
switch ( action.type ) {
|
|
case 'RECEIVE':
|
|
return action.data;
|
|
default:
|
|
return state;
|
|
}
|
|
};
|
|
|
|
// Select state both without and with a resolver.
|
|
const selectors = {
|
|
selectorWithoutResolver: ( state ) => state,
|
|
selectorWithResolver: ( state ) => state,
|
|
};
|
|
|
|
// The resolver receives data after a little delay.
|
|
const resolvers = {
|
|
*selectorWithResolver() {
|
|
yield new Promise( ( r ) => setTimeout( r, 10 ) );
|
|
return { type: 'RECEIVE', data: 'resolved-data' };
|
|
},
|
|
};
|
|
|
|
// actions that call the tested controls and return the selected value.
|
|
const actions = {
|
|
*resolveWithoutResolver() {
|
|
const value = yield controls.resolveSelect(
|
|
'test/select',
|
|
'selectorWithoutResolver'
|
|
);
|
|
return value;
|
|
},
|
|
*resolveWithResolver() {
|
|
const value = yield controls.resolveSelect(
|
|
'test/select',
|
|
'selectorWithResolver'
|
|
);
|
|
return value;
|
|
},
|
|
*selectWithoutResolver() {
|
|
const value = yield controls.select(
|
|
'test/select',
|
|
'selectorWithoutResolver'
|
|
);
|
|
return value;
|
|
},
|
|
*selectWithResolver() {
|
|
const value = yield controls.select(
|
|
'test/select',
|
|
'selectorWithResolver'
|
|
);
|
|
return value;
|
|
},
|
|
};
|
|
|
|
registry.registerStore( 'test/select', {
|
|
reducer,
|
|
actions,
|
|
selectors,
|
|
resolvers,
|
|
} );
|
|
|
|
return registry;
|
|
}
|
|
|
|
describe( 'resolveSelect', () => {
|
|
it( 'invokes selector without a resolver', async () => {
|
|
const registry = createSelectTestRegistry();
|
|
const value = await registry
|
|
.dispatch( 'test/select' )
|
|
.resolveWithoutResolver();
|
|
// Returns the state value without waiting for any resolver.
|
|
expect( value ).toBe( null );
|
|
} );
|
|
|
|
it( 'resolves selector with a resolver', async () => {
|
|
const registry = createSelectTestRegistry();
|
|
const value = await registry
|
|
.dispatch( 'test/select' )
|
|
.resolveWithResolver();
|
|
// Waits for the resolver to resolve and returns the resolved data.
|
|
// Never returns the initial `null` state.
|
|
expect( value ).toBe( 'resolved-data' );
|
|
} );
|
|
} );
|
|
|
|
describe( 'select', () => {
|
|
it( 'invokes selector without a resolver', async () => {
|
|
const registry = createSelectTestRegistry();
|
|
const value = await registry
|
|
.dispatch( 'test/select' )
|
|
.selectWithoutResolver();
|
|
// Returns the state value without waiting for any resolver.
|
|
expect( value ).toBe( null );
|
|
} );
|
|
|
|
it( 'invokes selector with a resolver', async () => {
|
|
const registry = createSelectTestRegistry();
|
|
// Check that the action with a control returns the initial state
|
|
// without waiting for any resolver.
|
|
const value = await registry
|
|
.dispatch( 'test/select' )
|
|
.selectWithResolver();
|
|
expect( value ).toBe( null );
|
|
|
|
// Check that re-running the action immediately still returns
|
|
// the initial state, as the resolution is still running.
|
|
const value2 = await registry
|
|
.dispatch( 'test/select' )
|
|
.selectWithResolver();
|
|
expect( value2 ).toBe( null );
|
|
} );
|
|
} );
|
|
|
|
describe( 'dispatch', () => {
|
|
function createDispatchTestRegistry() {
|
|
const registry = createRegistry();
|
|
|
|
// Store stores a counter that can be incremented.
|
|
const reducer = ( state = 0, action ) => {
|
|
switch ( action.type ) {
|
|
case 'INC':
|
|
return state + 1;
|
|
default:
|
|
return state;
|
|
}
|
|
};
|
|
|
|
const actions = {
|
|
// increment the counter.
|
|
inc() {
|
|
return { type: 'INC' };
|
|
},
|
|
// Increment the counter twice in an async routine with controls.
|
|
*doubleInc() {
|
|
yield controls.dispatch( 'test/dispatch', 'inc' );
|
|
yield controls.dispatch( 'test/dispatch', 'inc' );
|
|
},
|
|
};
|
|
|
|
const selectors = {
|
|
get: ( state ) => state,
|
|
};
|
|
|
|
registry.registerStore( 'test/dispatch', {
|
|
reducer,
|
|
actions,
|
|
selectors,
|
|
} );
|
|
|
|
return registry;
|
|
}
|
|
|
|
it( 'invokes dispatch action', async () => {
|
|
const registry = createDispatchTestRegistry();
|
|
expect( registry.select( 'test/dispatch' ).get() ).toBe( 0 );
|
|
await registry.dispatch( 'test/dispatch' ).doubleInc();
|
|
expect( registry.select( 'test/dispatch' ).get() ).toBe( 2 );
|
|
} );
|
|
} );
|
|
} );
|