Skip to content

Commit

Permalink
Fix types in react-enty
Browse files Browse the repository at this point in the history
  • Loading branch information
allanhortle committed Oct 8, 2023
1 parent e213ee5 commit f2f4ea9
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 75 deletions.
5 changes: 5 additions & 0 deletions packages/enty/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
rules: {
'prettier/prettier': 0
}
};
2 changes: 1 addition & 1 deletion packages/react-enty/src/EntityApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export type Request<T, V> = {
type RequestFunction = (variables?: any, meta?: any) => Promise<any> | AsyncIterator<any>;

type MappedTransform<T> = {
[K in keyof T]: T[K] extends RequestFunction
[K in keyof T]: T[K] extends SideEffect
? Request<
Awaited<ReturnType<T[K]>>,
Parameters<T[K]>[0] extends undefined ? void : Parameters<T[K]>[0]
Expand Down
1 change: 0 additions & 1 deletion packages/react-enty/src/__tests__/EntityApi-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {ObjectSchema} from 'enty';
import {useEffect} from 'react';
import {asyncUpdate, ExpectsMessage} from './RequestSuite';
import {mount} from 'enzyme';
import Hash from '../util/Hash';

describe('exports', () => {
const api = EntityApi(
Expand Down
37 changes: 16 additions & 21 deletions packages/react-enty/src/__tests__/EntityReducerFactory-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import resetAction from '../api/resetAction';
//

const baseState = {
baseSchema: new ObjectSchema({}),
schemas: {},
response: {},
error: {},
Expand Down Expand Up @@ -67,7 +66,7 @@ test('EntityReducerFactory normalizes a reuslt', () => {

const exampleReceiveAction = {
type: 'ENTY_RECEIVE' as const,
meta: {responseKey: 'TEST'},
meta: {responseKey: 'TEST', name: 'foo'},
payload: examplePayload
};

Expand All @@ -80,7 +79,7 @@ describe('EntityReducer requestState', () => {
const data = EntityReducer(null, {
type: 'ENTY_FETCH' as const,
payload: null,
meta: {responseKey: 'TEST'}
meta: {responseKey: 'TEST', name: 'foo'}
}).requestState.TEST;
expect(data.isFetching).toBe(true);
});
Expand All @@ -92,7 +91,7 @@ describe('EntityReducer requestState', () => {
requestState: {TEST: RequestState.fetching()},
response: {TEST: {}}
},
{type: 'ENTY_FETCH' as const, payload: null, meta: {responseKey: 'TEST'}}
{type: 'ENTY_FETCH' as const, payload: null, meta: {responseKey: 'TEST', name: 'foo'}}
).requestState.TEST;
expect(data.isRefetching).toBe(true);
});
Expand All @@ -101,12 +100,12 @@ describe('EntityReducer requestState', () => {
let stateA = EntityReducer(null, {
type: 'ENTY_FETCH' as const,
payload: null,
meta: {responseKey: 'foo'}
meta: {responseKey: 'foo', name: 'foo'}
});
let stateB = EntityReducer(stateA, {
type: 'ENTY_FETCH' as const,
payload: null,
meta: {responseKey: 'foo'}
meta: {responseKey: 'foo', name: 'foo'}
});
expect(stateB.requestState.foo.isRefetching).toBe(undefined);
expect(stateB.requestState.foo.isFetching).toBe(true);
Expand All @@ -118,7 +117,7 @@ describe('EntityReducer requestState', () => {
// @ts-ignore - intentionally bad types
type: 'nothing',
payload: null,
meta: {responseKey: 'nothing'}
meta: {responseKey: 'nothing', name: 'foo'}
}).requestState.nothing
).toBeUndefined();
});
Expand All @@ -130,19 +129,15 @@ describe('EntityReducer requestState', () => {
EntityReducer(null, {
type: 'ENTY_ERROR',
payload: 'errorPayload',
meta: {responseKey: 'TEST'}
meta: {responseKey: 'TEST', name: 'foo'}
}).requestState.TEST.value()
).toBe('errorPayload');
});
});

describe('EntityReducer Config', () => {
const action = (type: Action['type']) =>
({type, payload: null, meta: {responseKey: type}} as const);
test('the supplied schema is not mutated when reducing', () => {
// @ts-ignore - intentionally bad types
expect(EntityReducer(null, action('nothing')).baseSchema).toBe(schema);
});
({type, payload: null, meta: {responseKey: type, name: 'foo'}} as const);

test('response starts with an empty object', () => {
// @ts-ignore - intentionally bad types
Expand Down Expand Up @@ -177,7 +172,7 @@ describe('EntityReducer Normalizing', () => {
test('it will store normalized results on _result.responseKey', () => {
const action = {
type: 'ENTY_RECEIVE',
meta: {responseKey: 'TEST'},
meta: {responseKey: 'TEST', name: 'foo'},
payload: {
subreddit: {
fullnameId: 'MK',
Expand All @@ -192,7 +187,7 @@ describe('EntityReducer Normalizing', () => {
test('it will store normalized data on _entities.type.id', () => {
const action = {
type: 'ENTY_RECEIVE',
meta: {responseKey: 'TEST'},
meta: {responseKey: 'TEST', name: 'foo'},
payload: {
subreddit: {
fullnameId: 'MK',
Expand All @@ -209,7 +204,7 @@ describe('EntityReducer Normalizing', () => {
test('it will store deep entities', () => {
const action = {
type: 'ENTY_RECEIVE',
meta: {responseKey: 'TEST'},
meta: {responseKey: 'TEST', name: 'foo'},
payload: {
subreddit: {
fullnameId: 'MK',
Expand All @@ -227,7 +222,7 @@ describe('EntityReducer Normalizing', () => {
const action = (payload: any) =>
({
type: 'ENTY_RECEIVE',
meta: {responseKey: 'TEST'},
meta: {responseKey: 'TEST', name: 'foo'},
payload
} as const);

Expand Down Expand Up @@ -286,7 +281,7 @@ describe('no schema reducer', () => {
const stateA = reducer(null, {
type: 'ENTY_RECEIVE',
payload: 'FOO',
meta: {responseKey: '123'}
meta: {responseKey: '123', name: 'foo'}
});

expect(stateA.entities).toEqual({});
Expand All @@ -297,7 +292,7 @@ describe('no schema reducer', () => {
const stateB = reducer(stateA, {
type: 'ENTY_RECEIVE',
payload: 'BAR',
meta: {responseKey: '456'}
meta: {responseKey: '456', name: 'foo'}
});
expect(stateB.response['123']).toBe('FOO');
expect(stateB.response['456']).toBe('BAR');
Expand All @@ -318,7 +313,7 @@ describe('remove entity', () => {
const state = reducer(initialState, {
type: 'ENTY_REMOVE' as const,
payload: ['foo', 'bar'],
meta: {responseKey: ''}
meta: {responseKey: '', name: 'foo'}
});
expect(state.entities.foo.bar).toBe(REMOVED_ENTITY);
expect(state.entities.baz.qux).not.toBe(REMOVED_ENTITY);
Expand All @@ -332,7 +327,7 @@ describe('ENTY_RESET', () => {
const stateA = reducer(null, {
type: 'ENTY_RECEIVE',
payload: 'FOO',
meta: {responseKey: '123'}
meta: {responseKey: '123', name: 'foo'}
});
expect(stateA.response['123']).toBe('FOO');
expect(stateA.requestState['123'].isSuccess).toBe(true);
Expand Down
15 changes: 4 additions & 11 deletions packages/react-enty/src/__tests__/ProviderFactory-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ describe('Component', () => {
);
}).toMatchObject([
{
baseSchema: undefined,
entities: {foo: 'component'},
error: {},
requestState: {},
Expand All @@ -63,8 +62,6 @@ describe('Component', () => {
);
}).toMatchObject([
{
//baseMeta: {foo: 'bar'},
baseSchema: undefined,
error: {},
requestState: {},
response: {},
Expand Down Expand Up @@ -142,7 +139,6 @@ describe('Hoc', () => {
);
}).toMatchObject([
{
baseSchema: undefined,
entities: {foo: 'hoc'},
error: {},
requestState: {},
Expand All @@ -158,15 +154,12 @@ describe('Hoc', () => {

describe('Debugging', () => {
it('will log reducer state if debug prop is provided', () => {
const group = jest.spyOn(console, 'groupCollapsed').mockImplementation(() => {});
const groupEnd = jest.spyOn(console, 'groupEnd').mockImplementation(() => {});
const log = jest.spyOn(console, 'log').mockImplementation(() => {});
const {Provider} = ProviderFactory({});
mount(<Provider debug="Foo" />);
mount(<Provider debug />);

expect(group).toHaveBeenCalled();
expect(groupEnd).toHaveBeenCalled();
expect(log).toHaveBeenCalled();

group.mockRestore();
groupEnd.mockRestore();
log.mockRestore();
});
});
14 changes: 0 additions & 14 deletions packages/react-enty/src/__tests__/RequestHook-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
badEntity,
bar,
baz,
obs,
entity
} from './RequestSuite';

Expand Down Expand Up @@ -62,19 +61,6 @@ describe('config', () => {
return null;
});
});

it('request will return undefined for observables', async () => {
expect.assertions(1);
mountWithProvider(() => () => {
const message = obs.useRequest();
useEffect(() => {
var pending = message.request();
expect(pending).toBeUndefined();
}, []);

return null;
});
});
});

describe('usage', () => {
Expand Down
26 changes: 12 additions & 14 deletions packages/react-enty/src/__tests__/RequestSuite.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,22 @@ import {mount} from 'enzyme';

function setupTests() {
const fooEntity = new EntitySchema('foo');
//const {Provider, foo, fooError, badEntity, bar, baz, obs, entity} = EntityApi(
const api = EntityApi(
{
foo: (data: string = 'foo') => Promise.resolve({data}),
entity: (foo: {id: string; name: string} = {id: '123', name: 'foo'}) =>
Promise.resolve({foo}),
badEntity: (foo: {name: string} = {name: 'foo'}) => Promise.resolve({foo}),
fooError: () => Promise.reject('ouch!'),
bar: (data: string = 'bar') => Promise.resolve({data}),
baz: (data: string = 'requested-baz') => Promise.resolve({data}),
obs: () => ({subscribe: () => {}})
foo: async (data: string = 'foo') => ({data}),
entity: async (foo: {id: string; name: string} = {id: '123', name: 'foo'}) => ({foo}),
badEntity: async (foo: {name: string} = {name: 'foo'}) => ({foo}),
fooError: async () => {
throw new Error('ouch!');
},
bar: async (data: string = 'bar') => ({data}),
baz: async (data: string = 'requested-baz') => ({data})
},
new ObjectSchema({
foo: fooEntity
})
);
const {Provider, foo, fooError, badEntity, bar, baz, obs, entity} = api;
const {Provider, foo, fooError, badEntity, bar, baz, entity} = api;

function ExpectsMessage(props: {
message: Message<any, any>;
Expand Down Expand Up @@ -73,15 +72,14 @@ function setupTests() {
foo,
bar,
baz,
obs,
fooError
};
}

export const {mountWithProvider, foo, bar, baz, obs, badEntity, entity, fooError, ExpectsMessage} =
export const {mountWithProvider, foo, bar, baz, badEntity, entity, fooError, ExpectsMessage} =
setupTests();

export function asyncUpdate(wrapper: any) {
export async function asyncUpdate(wrapper: any) {
return new Promise((resolve) => setTimeout(resolve, 0)).then(() => wrapper.update());
}

Expand Down Expand Up @@ -145,7 +143,7 @@ export async function errorOnLoad(testFn: TestFn) {
let wrapper = mountWithProvider(testFn);
expect(wrapper).toBeFetching();
await asyncUpdate(wrapper);
expect(wrapper).toBeError('ouch!');
expect(wrapper).toBeError(new Error('ouch!'));
}

export async function fetchBadEntity(testFn: TestFn) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import createRequestAction from '../createRequestAction';

const payload = 'PAYLOAD';
const meta = {responseKey: 'foo'};
const meta = {responseKey: 'foo', name: 'foo'};

describe('observable support', () => {
const observable = (fn: any) => ({
Expand Down Expand Up @@ -118,7 +118,7 @@ describe('promise support', () => {
const dispatch = jest.fn();
const getState = jest.fn();
const request = createRequestAction(() => Promise.reject('BORKD'));
const meta = {responseKey: '123'};
const meta = {responseKey: '123', name: 'foo'};
try {
await request(payload, meta)(dispatch, getState);
} catch (e) {
Expand Down Expand Up @@ -200,7 +200,7 @@ describe('async generators', () => {
describe('general', () => {
it('returns a function accepts payload/meta that returns a redux thunk', () => {
const payloadFunction = createRequestAction(() => Promise.resolve());
const thunk = payloadFunction('bar', {responseKey: '123'});
const thunk = payloadFunction('bar', {responseKey: '123', name: 'foo'});

expect(typeof payloadFunction).toBe('function');
expect(typeof thunk).toBe('function');
Expand All @@ -212,11 +212,11 @@ describe('general', () => {
const getState = jest.fn();

const payload = createRequestAction(async () => 'foo');
const payloadA = payload('foo', {responseKey: '', returnResponse: true})(
const payloadA = payload('foo', {responseKey: '', name: 'foo', returnResponse: true})(
dispatch,
getState
);
const payloadB = payload('foo', {responseKey: '', returnResponse: false})(
const payloadB = payload('foo', {responseKey: '', name: 'foo', returnResponse: false})(
dispatch,
getState
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {act, renderHook} from '@testing-library/react-hooks';
import {ObjectSchema} from 'enty';

const action = <T>(payload: T) => {
return {type: 'ENTY_RECEIVE', payload, meta: {responseKey: ''}} as const;
return {type: 'ENTY_RECEIVE', payload, meta: {name: 'foo', responseKey: ''}} as const;
};
const initialState = {
baseSchema: new ObjectSchema({}),
Expand Down
14 changes: 7 additions & 7 deletions packages/react-enty/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2867,9 +2867,9 @@ caniuse-api@^3.0.0:
lodash.uniq "^4.5.0"

caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001219:
version "1.0.30001402"
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001402.tgz"
integrity sha512-Mx4MlhXO5NwuvXGgVb+hg65HZ+bhUYsz8QtDGDo2QmaJS2GBX47Xfi2koL86lc8K+l+htXeTEB/Aeqvezoo6Ew==
version "1.0.30001546"
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001546.tgz"
integrity sha512-zvtSJwuQFpewSyRrI3AsftF6rM0X80mZkChIt1spBGEvRglCrjTniXvinc8JKRoqTwXAgvqTImaN9igfSMtUBw==

capture-exit@^2.0.0:
version "2.0.0"
Expand Down Expand Up @@ -3825,10 +3825,10 @@ entities@^2.0.0:
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==

enty@^2.0.0-alpha.13:
version "2.0.0-alpha.13"
resolved "https://registry.yarnpkg.com/enty/-/enty-2.0.0-alpha.13.tgz#64f480e748c0037cb559e32068996d913ac88df4"
integrity sha512-pvtmAdOJh/BDZByKuOMpfFQZ4dTXBFin8QfTOvWMDH5DUhbIqrZxBFzXuI8tezoN6ozF7NdKaVdH1H8h/c8KeQ==
enty@^2.0.0-alpha.16:
version "2.0.0-alpha.16"
resolved "https://registry.yarnpkg.com/enty/-/enty-2.0.0-alpha.16.tgz#4dc2185466d1732a119f7b1463a5bdf6c706c183"
integrity sha512-huWNHs30cRrDvg1+j3gGOMHth2QayssZLYHwhnBCfHLr14AOKirlkAvqdBKq6FbBvbb2qROjtW23zukqL8SwhQ==

enzyme-matchers@^7.1.2:
version "7.1.2"
Expand Down

0 comments on commit f2f4ea9

Please sign in to comment.