Skip to content
This repository has been archived by the owner on Aug 23, 2023. It is now read-only.

Commit

Permalink
feat(selector): rename and expose loaded selectors (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
drewcur committed Aug 18, 2022
1 parent ddb49b4 commit 3f6cfba
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 46 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,9 @@ These actions return a promise that resolves with the fetched data on successful

### Selectors
#### `getResource({ resource, id })(state)`
#### `getResourceIsLoaded({ resource, id })(state)`
#### `getCollection({ resource, id, opts })(state)`
#### `getCollectionIsLoaded({ resource, id, opts })(state)`

### Cleaning Actions
#### `clearResource({ resource, id, opts })`
Expand Down
28 changes: 14 additions & 14 deletions __tests__/actions/crud.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ import {
} from '../../src/actions/crud';

jest.mock('../../src/selectors', () => ({
resourceIsLoaded: jest.fn(),
getResourceIsLoaded: jest.fn(),
getResource: jest.fn(() => () => {}),
resourceIsLoading: jest.fn(),
getResourceLoadPromise: jest.fn(),
collectionIsLoaded: jest.fn(),
getCollectionIsLoaded: jest.fn(),
getCollection: jest.fn(() => () => []),
collectionIsLoading: jest.fn(),
getCollectionLoadPromise: jest.fn(),
Expand All @@ -54,7 +54,7 @@ describe('CRUD actions', () => {
describe('loadResource', () => {
it('should load a single resource if it is not loaded or loading', async () => {
const thunk = loadResource({ resource, id, opts });
require('../../src/selectors').resourceIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
require('../../src/selectors').getResourceIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
require('../../src/selectors').resourceIsLoading.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
await thunk(dispatch, getState);
expect(dispatch).toHaveBeenCalledWith(mockFetchPromise);
Expand All @@ -65,7 +65,7 @@ describe('CRUD actions', () => {

it('should resolve with the cached resource if it is already loaded', async () => {
const thunk = loadResource({ resource, id, opts });
require('../../src/selectors').resourceIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').getResourceIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
await thunk(dispatch, getState);
expect(dispatch).not.toHaveBeenCalled();
expect(executeFetch).not.toHaveBeenCalled();
Expand All @@ -75,7 +75,7 @@ describe('CRUD actions', () => {
const error = new Error('load error');
try {
const thunk = loadResource({ resource, id, opts });
require('../../src/selectors').resourceIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').getResourceIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').getResource.mockImplementationOnce(() => () => error); // eslint-disable-line global-require
await thunk(dispatch, getState);
} catch (e) {
Expand All @@ -87,7 +87,7 @@ describe('CRUD actions', () => {

it('should return with the loading promise if it is already in progress', async () => {
const thunk = loadResource({ resource, id, opts });
require('../../src/selectors').resourceIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
require('../../src/selectors').getResourceIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
require('../../src/selectors').resourceIsLoading.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').getResourceLoadPromise.mockImplementationOnce(() => () => Promise.resolve()); // eslint-disable-line global-require
await thunk(dispatch, getState);
Expand All @@ -99,7 +99,7 @@ describe('CRUD actions', () => {
const thunk = loadResource({
resource, id, opts, forceFetch: true,
});
require('../../src/selectors').resourceIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').getResourceIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').resourceIsLoading.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
await thunk(dispatch, getState);
expect(dispatch).toHaveBeenCalledWith(mockFetchPromise);
Expand All @@ -112,7 +112,7 @@ describe('CRUD actions', () => {
const thunk = loadResource({
resource, id, opts, forceFetch: true,
});
require('../../src/selectors').resourceIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
require('../../src/selectors').getResourceIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
require('../../src/selectors').resourceIsLoading.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
await thunk(dispatch, getState);
expect(dispatch).toHaveBeenCalledWith(mockFetchPromise);
Expand All @@ -125,7 +125,7 @@ describe('CRUD actions', () => {
describe('loadCollection', () => {
it('should load the collection if it is not loaded or loading', async () => {
const thunk = loadCollection({ resource, opts });
require('../../src/selectors').collectionIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
require('../../src/selectors').getCollectionIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
require('../../src/selectors').collectionIsLoading.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
await thunk(dispatch, getState);
expect(dispatch).toHaveBeenCalledWith(mockFetchPromise);
Expand All @@ -134,7 +134,7 @@ describe('CRUD actions', () => {

it('should not refetch the collection if it is already loaded', async () => {
const thunk = loadCollection({ resource, opts });
require('../../src/selectors').collectionIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').getCollectionIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
await thunk(dispatch, getState);
expect(dispatch).not.toHaveBeenCalled();
expect(executeFetch).not.toHaveBeenCalled();
Expand All @@ -144,7 +144,7 @@ describe('CRUD actions', () => {
const error = new Error('load error');
try {
const thunk = loadCollection({ resource, id, opts });
require('../../src/selectors').collectionIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').getCollectionIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').getCollection.mockImplementationOnce(() => () => error); // eslint-disable-line global-require
await thunk(dispatch, getState);
} catch (e) {
Expand All @@ -156,7 +156,7 @@ describe('CRUD actions', () => {

it('should not refetch the resource if a fetch is already in progress', async () => {
const thunk = loadCollection({ resource, opts });
require('../../src/selectors').collectionIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
require('../../src/selectors').getCollectionIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
require('../../src/selectors').collectionIsLoading.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').getCollectionLoadPromise.mockImplementationOnce(() => () => Promise.resolve()); // eslint-disable-line global-require
await thunk(dispatch, getState);
Expand All @@ -166,7 +166,7 @@ describe('CRUD actions', () => {

it('should load the collection if the collection is loaded, but forceFetch is specified', async () => {
const thunk = loadCollection({ resource, opts, forceFetch: true });
require('../../src/selectors').collectionIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').getCollectionIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').collectionIsLoading.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
await thunk(dispatch, getState);
expect(dispatch).toHaveBeenCalledWith(mockFetchPromise);
Expand All @@ -177,7 +177,7 @@ describe('CRUD actions', () => {
const thunk = loadCollection({
resource, id, opts, forceFetch: true,
});
require('../../src/selectors').collectionIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
require('../../src/selectors').getCollectionIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
require('../../src/selectors').collectionIsLoading.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
await thunk(dispatch, getState);
expect(dispatch).toHaveBeenCalledWith(mockFetchPromise);
Expand Down
24 changes: 12 additions & 12 deletions __tests__/actions/query.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ jest.mock('../../src/actions/crud', () => ({
jest.mock('../../src/selectors', () => ({
getResource: jest.fn(() => () => 'resource'),
getCollection: jest.fn(() => () => 'collection'),
resourceIsLoaded: jest.fn(),
collectionIsLoaded: jest.fn(),
getResourceIsLoaded: jest.fn(),
getCollectionIsLoaded: jest.fn(),
}));

jest.mock('../../src/actions/asyncSideEffects', () => ({
Expand All @@ -47,7 +47,7 @@ describe('iguazu query actions', () => {

describe('queryResource', () => {
it('should return a loading response if the resource is loading', () => {
require('../../src/selectors').resourceIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
require('../../src/selectors').getResourceIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
const thunk = queryResource({ resource, id, opts });
const loadResponse = thunk(dispatch, getState);
expect(loadResponse.data).toEqual('resource');
Expand All @@ -57,7 +57,7 @@ describe('iguazu query actions', () => {
});

it('should return a loaded response if the resource is loaded', () => {
require('../../src/selectors').resourceIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').getResourceIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
const thunk = queryResource({ resource, id, opts });
const loadResponse = thunk(dispatch, getState);
expect(loadResponse.data).toEqual('resource');
Expand All @@ -67,7 +67,7 @@ describe('iguazu query actions', () => {
});

it('should return a loading response if the resource is loaded, but forceFetch is specified', () => {
require('../../src/selectors').resourceIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').getResourceIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
const thunk = queryResource({
resource, id, opts, forceFetch: true,
});
Expand All @@ -79,7 +79,7 @@ describe('iguazu query actions', () => {
});

it('should indicate an error occured if applicable', () => {
require('../../src/selectors').resourceIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').getResourceIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').getResource.mockImplementationOnce(() => () => loadError); // eslint-disable-line global-require
const thunk = queryResource({ resource, id, opts });
const loadResponse = thunk(dispatch, getState);
Expand All @@ -91,7 +91,7 @@ describe('iguazu query actions', () => {
const { handleQueryPromiseRejection } = require('../../src/actions/asyncSideEffects'); // eslint-disable-line global-require
let promise;
try {
require('../../src/selectors').resourceIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
require('../../src/selectors').getResourceIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
require('../../src/actions/crud').loadResource.mockImplementationOnce(() => Promise.reject(new Error('async error'))); // eslint-disable-line global-require
const thunk = queryResource({ resource, id, opts });
const loadResponse = thunk(dispatch, getState);
Expand All @@ -106,7 +106,7 @@ describe('iguazu query actions', () => {

describe('queryCollection', () => {
it('should return a loading response if the collection is loading', () => {
require('../../src/selectors').collectionIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
require('../../src/selectors').getCollectionIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
const thunk = queryCollection({ resource, id, opts });
const loadResponse = thunk(dispatch, getState);
expect(loadResponse.data).toEqual('collection');
Expand All @@ -115,7 +115,7 @@ describe('iguazu query actions', () => {
});

it('should return a loaded response if the collection is loaded', () => {
require('../../src/selectors').collectionIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').getCollectionIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
const thunk = queryCollection({ resource, id, opts });
const loadResponse = thunk(dispatch, getState);
expect(loadResponse.data).toEqual('collection');
Expand All @@ -124,7 +124,7 @@ describe('iguazu query actions', () => {
});

it('should return a loading response if the collection is loaded, but forceFetch is specified', () => {
require('../../src/selectors').collectionIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').getCollectionIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
const thunk = queryCollection({
resource, id, opts, forceFetch: true,
});
Expand All @@ -135,7 +135,7 @@ describe('iguazu query actions', () => {
});

it('should indicate an error occured if applicable', () => {
require('../../src/selectors').collectionIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').getCollectionIsLoaded.mockImplementationOnce(() => () => true); // eslint-disable-line global-require
require('../../src/selectors').getCollection.mockImplementationOnce(() => () => loadError); // eslint-disable-line global-require
const thunk = queryCollection({ resource, id, opts });
const loadResponse = thunk(dispatch, getState);
Expand All @@ -147,7 +147,7 @@ describe('iguazu query actions', () => {
const { handleQueryPromiseRejection } = require('../../src/actions/asyncSideEffects'); // eslint-disable-line global-require
let promise;
try {
require('../../src/selectors').collectionIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
require('../../src/selectors').getCollectionIsLoaded.mockImplementationOnce(() => () => false); // eslint-disable-line global-require
require('../../src/actions/crud').loadCollection.mockImplementationOnce(() => Promise.reject(new Error('async error'))); // eslint-disable-line global-require
const thunk = queryCollection({ resource, id, opts });
const loadResponse = thunk(dispatch, getState);
Expand Down
20 changes: 10 additions & 10 deletions __tests__/selectors.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ import {
import { configureIguazuREST } from '../src/config';

import {
resourceIsLoaded,
getResourceIsLoaded,
getResource,
resourceIsLoading,
getResourceLoadPromise,
collectionIsLoaded,
getCollectionIsLoaded,
getCollection,
collectionIsLoading,
getCollectionLoadPromise,
Expand All @@ -43,7 +43,7 @@ describe('selectors', () => {
configureIguazuREST({ getToState: (state) => state.deep.resources });
});

describe('resourceIsLoaded', () => {
describe('getResourceIsLoaded', () => {
it('should return true if the resource is loaded', () => {
const state = {
deep: {
Expand All @@ -52,7 +52,7 @@ describe('selectors', () => {
}),
},
};
expect(resourceIsLoaded({ resource, id })(state)).toBe(true);
expect(getResourceIsLoaded({ resource, id })(state)).toBe(true);
});

it('should return false if the resource is not loaded', () => {
Expand All @@ -63,7 +63,7 @@ describe('selectors', () => {
}),
},
};
expect(resourceIsLoaded({ resource, id })(state)).toBe(false);
expect(getResourceIsLoaded({ resource, id })(state)).toBe(false);
});
});

Expand Down Expand Up @@ -138,7 +138,7 @@ describe('selectors', () => {
}),
},
};
expect(resourceIsLoaded({ resource, id })(state)).toBe(true);
expect(getResourceIsLoaded({ resource, id })(state)).toBe(true);
});

it('should return false if the resource is not loading', () => {
Expand Down Expand Up @@ -167,7 +167,7 @@ describe('selectors', () => {
});
});

describe('collectionIsLoaded', () => {
describe('getCollectionIsLoaded', () => {
it('should return true if the collection is loaded', () => {
const collectionIdHash = getCollectionIdHash();
const queryHash = getQueryHash();
Expand All @@ -178,7 +178,7 @@ describe('selectors', () => {
}),
},
};
expect(collectionIsLoaded({ resource })(state)).toBe(true);
expect(getCollectionIsLoaded({ resource })(state)).toBe(true);
});

it('should return true if the collection is loaded with error', () => {
Expand All @@ -200,7 +200,7 @@ describe('selectors', () => {
}),
},
};
expect(collectionIsLoaded({ resource })(state)).toBe(true);
expect(getCollectionIsLoaded({ resource })(state)).toBe(true);
});

it('should return false if the collection is not loaded', () => {
Expand All @@ -211,7 +211,7 @@ describe('selectors', () => {
}),
},
};
expect(collectionIsLoaded({ resource })(state)).toBe(false);
expect(getCollectionIsLoaded({ resource })(state)).toBe(false);
});
});

Expand Down
8 changes: 4 additions & 4 deletions src/actions/crud.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
*/

import {
resourceIsLoaded,
getResourceIsLoaded,
getResource,
resourceIsLoading,
getResourceLoadPromise,
collectionIsLoaded,
getCollectionIsLoaded,
getCollection,
collectionIsLoading,
getCollectionLoadPromise,
Expand All @@ -32,7 +32,7 @@ export function loadResource({
return (dispatch, getState) => {
const state = getState();
let promise;
if (resourceIsLoaded({ resource, id })(state) && !forceFetch) {
if (getResourceIsLoaded({ resource, id })(state) && !forceFetch) {
const data = getResource({ resource, id })(state);
promise = data instanceof Error ? Promise.reject(data) : Promise.resolve(data);
} else if (resourceIsLoading({ resource, id })(state) && !forceFetch) {
Expand All @@ -53,7 +53,7 @@ export function loadCollection({
return (dispatch, getState) => {
const state = getState();
let promise;
if (collectionIsLoaded({ resource, id, opts })(state) && !forceFetch) {
if (getCollectionIsLoaded({ resource, id, opts })(state) && !forceFetch) {
const data = getCollection({ resource, id, opts })(state);
promise = data instanceof Error ? Promise.reject(data) : Promise.resolve(data);
} else if (collectionIsLoading({ resource, id, opts })(state) && !forceFetch) {
Expand Down

0 comments on commit 3f6cfba

Please sign in to comment.