Skip to content

Commit

Permalink
refactor(uselazy): take and array of imports instead of Alien modules
Browse files Browse the repository at this point in the history
is not necessary to have two concepts of "module" just with redux modules is enough

#43
  • Loading branch information
aneurysmjs committed Jan 24, 2020
1 parent 4d32e8f commit 2ceb9f8
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 42 deletions.
48 changes: 18 additions & 30 deletions src/app/store/config/alienStore/useAlien.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ import alien from './alien';

import useAlien from './useAlien';

import { reduxModule, reduxModuleNoReducers, reduxModuleA, reduxModuleB } from './helpers/modules';
import {
reduxModule,
reduxModuleNoId,
reduxModuleNoReducers,
reduxModuleA,
reduxModuleB,
} from './helpers/modules';
import { withProvider, WrapperType } from './helpers/withProvider';

const WRONG_COMPONENT_PATH = './some/wrong/component/path';
Expand All @@ -29,15 +35,9 @@ describe('useAlien', () => {
type ReduxModuleBType = Promise<typeof reduxModuleB>;

it('should render "null" at first and then resolve each module', async () => {
const alienModuleA = {
id: 'alien-module-a',
getModule: (): ReduxModuleAType => Promise.resolve(reduxModuleA),
};
const alienModuleA = (): ReduxModuleAType => Promise.resolve(reduxModuleA);

const alienModuleB = {
id: 'alien-module-b',
getModule: (): ReduxModuleBType => Promise.resolve(reduxModuleB),
};
const alienModuleB = (): ReduxModuleBType => Promise.resolve(reduxModuleB);

const { result, waitForNextUpdate } = renderHook(() => useAlien([alienModuleA, alienModuleB]), {
wrapper,
Expand All @@ -63,10 +63,7 @@ describe('useAlien', () => {
});

it('should call cb when unmounting', async () => {
const alienModule = {
id: 'some-alien-module',
getModule: (): ReduxModuleType => Promise.resolve(reduxModule),
};
const alienModule = (): ReduxModuleType => Promise.resolve(reduxModule);

const cb = jest.fn();

Expand All @@ -93,30 +90,24 @@ describe('useAlien', () => {
expect(cb).toHaveBeenCalledTimes(1);
});

it('should throw when alien module has no "id" or when is empty string', async () => {
const alienModule = {
getModule: (): ReduxModuleType => Promise.resolve(reduxModule),
};

it('should throw when a redux module has no "id" or when is empty string', async () => {
// @ts-ignore - "id" doesn't exist for testing purposes
const { result } = renderHook(() => useAlien([alienModule]), {
const alienModule = (): ReduxModuleType => Promise.resolve(reduxModuleNoId);

const { result, waitForNextUpdate } = renderHook(() => useAlien([alienModule]), {
wrapper,
});

// here there's no need to resolve the promise cuz it doesn't even get to be called
// await waitForNextUpdate();
await waitForNextUpdate();

expect(() => {
expect(result.current).not.toBe(undefined);
}).toThrow(Error('useAlienModule Error: Alien Module has no id'));
}).toThrow(Error('useAlienModule Error: Redux Module has no id'));
});

it('should throw when wrong import path', async () => {
const mockDispatch = jest.spyOn(store, 'dispatch');
const alienModule = {
id: 'some-alien-module',
getModule: (): ReduxModuleType => import(WRONG_COMPONENT_PATH),
};
const alienModule = (): ReduxModuleType => import(WRONG_COMPONENT_PATH);

const { result, waitForNextUpdate } = renderHook(() => useAlien([alienModule]), {
wrapper,
Expand All @@ -138,10 +129,7 @@ describe('useAlien', () => {
it('should throw when redux module has no reducers', async () => {
type ReduxModuleNoReducersType = Promise<typeof reduxModuleNoReducers>;

const alienModule = {
id: 'some-alien-module',
getModule: (): ReduxModuleNoReducersType => Promise.resolve(reduxModuleNoReducers),
};
const alienModule = (): ReduxModuleNoReducersType => Promise.resolve(reduxModuleNoReducers);

const { result, waitForNextUpdate } = renderHook(() => useAlien([alienModule]), {
wrapper,
Expand Down
26 changes: 14 additions & 12 deletions src/app/store/config/alienStore/useAlien.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { isEmpty, isNil, anyPass, any } from 'ramda';
import { AlienStore } from './alien';

export interface ReduxModule<T = {}> {
id: string;
reducers: {
[K: string]: Reducer<T>;
};
Expand All @@ -20,12 +21,10 @@ export interface ReduxModule<T = {}> {
export type AlienResult = Omit<ReduxModule, 'reducers'>;

export interface AlienModule<T = {}> {
id: string;
getModule: () => Promise<ReduxModule<T>>;
initialActions?: Array<string>;
}

const check: <T>(obj: T) => boolean = anyPass([isNil, isEmpty]);
const check: <T>(thing: T) => boolean = anyPass([isNil, isEmpty]);

function errorHandler<T>(errorOrObj: T): T {
if (errorOrObj) {
Expand All @@ -39,7 +38,7 @@ function errorHandler<T>(errorOrObj: T): T {
}

function useAlien<T>(
alienModules: [AlienModule<T>],
reduxImports: [() => Promise<ReduxModule<T>>],
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
cb: () => void = () => {},
): AlienResult | null {
Expand All @@ -52,15 +51,18 @@ function useAlien<T>(
useEffect(() => {
(async (): Promise<void> => {
try {
if (any(({ id }) => check(id), alienModules)) {
throw new Error('Alien Module has no id');
}
const promises = alienModules.map(alienModule => alienModule.getModule());
const nextReduxModule = {} as ReduxModule<T>;

const promises = reduxImports.map(reduxImport => reduxImport());

const resolvedModules = await Promise.all(promises);
const reduxModules = await Promise.all(promises);

const result = reduxModules.reduce(
(acc, { id, reducers, actions, selectors }: ReduxModule<T>) => {
if (check(id)) {
throw new Error('Redux Module has no id');
}

const result = resolvedModules.reduce(
(acc, { reducers, actions, selectors }: ReduxModule<T>) => {
if (check(reducers)) {
throw new Error('Redux Module has no reducers');
}
Expand All @@ -82,7 +84,7 @@ function useAlien<T>(
}),
};
},
{},
nextReduxModule,
);

setAlien(result);
Expand Down

0 comments on commit 2ceb9f8

Please sign in to comment.