diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index fb3893c8..83dd5328 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -31,6 +31,9 @@ jobs: - name: Build run: | npm run build + - name: Integration + run: | + npm run e2e - name: Deploy if: matrix.node-version == '12.x' && github.ref == 'refs/heads/master' env: diff --git a/jest.e2e.config.json b/jest.e2e.config.json new file mode 100644 index 00000000..b66265d2 --- /dev/null +++ b/jest.e2e.config.json @@ -0,0 +1,12 @@ +{ + "preset": "ts-jest", + "moduleDirectories": ["./node_modules", "/node_modules", "."], + "moduleNameMapper": { + "src(.*)": "/dist$1" + }, + "testPathIgnorePatterns": [ + "./artifacts/", + "./dist/", + "./node_modules/" + ] +} diff --git a/package.json b/package.json index eae48261..00dcd7a3 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "clean": "rm -rf ./dist", "commit": "git-cz", "dedupe": "npm dedupe", + "e2e": "jest -c ./jest.e2e.config.json tests/index", "lint": "eslint . --max-warnings=0 --ext .js,.jsx,.ts,.tsx", "release": "semantic-release", "test": "jest", @@ -57,7 +58,8 @@ "coverageDirectory": "./artifacts/coverage", "coveragePathIgnorePatterns": [ "/node_modules", - "/tests" + "/tests", + "/e2e" ], "testPathIgnorePatterns": [ "./artifacts/", diff --git a/src/createAction.ts b/src/createAction.ts index 375330dc..3057fc19 100644 --- a/src/createAction.ts +++ b/src/createAction.ts @@ -2,7 +2,7 @@ export function createAction( type: T, prepare = (payload?: P): Partial> => ({ payload }), ): ActionCreator { - return function createAction(payload): Action { + return function createAction(payload) { const partialAction = prepare(payload); return { ...partialAction, type }; }; diff --git a/src/createContext.ts b/src/createContext.ts index a2f99603..9bfd8f87 100644 --- a/src/createContext.ts +++ b/src/createContext.ts @@ -5,7 +5,7 @@ import { setGlobalContext } from "./components/Context"; function createUnimplemented(objectName?: string): (m: string) => () => never { const prefix = objectName ? `${objectName}.` : ""; return function createUnimplemented(methodName) { - return function unimplemented(): never { + return function unimplemented() { throw new Error(`Unimplemented method: ${prefix}${methodName}`); }; }; diff --git a/src/createReducer.ts b/src/createReducer.ts index 9558dce4..a6bc38e3 100644 --- a/src/createReducer.ts +++ b/src/createReducer.ts @@ -11,7 +11,7 @@ export function createReducer< a !== undefined && Object.prototype.hasOwnProperty.call(actionTypeToReducer, a.type); - return function actionReducer(state = initialState, action?): S { + return function actionReducer(state = initialState, action?) { if (!isReducerActionType(action)) { return defaultReducer?.(state, action) ?? state; } diff --git a/src/utils/actionTypes.ts b/src/utils/actionTypes.ts index 8bf7290f..94b59d5c 100644 --- a/src/utils/actionTypes.ts +++ b/src/utils/actionTypes.ts @@ -1,6 +1,5 @@ -const randomString = (): string => Math.random().toString(36).substring(7); -const ns = (s: TemplateStringsArray): string => - `@@context/${s}/${randomString()}`; +const randomString = () => Math.random().toString(36).substring(7); +const ns = (s: TemplateStringsArray) => `@@context/${s}/${randomString()}`; export const ActionTypes = { INIT: ns`INIT`, diff --git a/src/utils/applyMiddleware.ts b/src/utils/applyMiddleware.ts index 9ca91bf8..202be98d 100644 --- a/src/utils/applyMiddleware.ts +++ b/src/utils/applyMiddleware.ts @@ -4,9 +4,7 @@ import { compose } from "./compose"; export function applyMiddleware( ...middlewares: Middleware[] ): ContextEnhance { - return function enhancer( - context: ContextValue, - ): ContextValue { + return function enhancer(context: ContextValue) { // eslint-disable-next-line @typescript-eslint/no-unused-vars function dispatchStub(...args: unknown[]): never { throw new Error( diff --git a/src/utils/combineReducers.ts b/src/utils/combineReducers.ts index 27a988b5..e95973ce 100644 --- a/src/utils/combineReducers.ts +++ b/src/utils/combineReducers.ts @@ -5,10 +5,7 @@ export function combineReducers( reducerMapping: DuckReducerMapping, ): Reducer, T, P> { const reducers = getEntries(reducerMapping); - return function ( - state: Record = initialState, - action, - ): Record { + return function (state: Record = initialState, action) { return reducers.reduce(function reduce(acc, [name, reducer]) { acc[name] = reducer(state[name], action); return acc; diff --git a/src/utils/combineSelectors.ts b/src/utils/combineSelectors.ts index e19d9eb1..0e788341 100644 --- a/src/utils/combineSelectors.ts +++ b/src/utils/combineSelectors.ts @@ -12,7 +12,7 @@ export function combineSelectors< if (!selectors) return; const duckSelectors = {} as SelectorMapping; for (const s of Object.keys(selectors) as Q[]) { - duckSelectors[s] = (state: S): R => + duckSelectors[s] = (state) => selectors[s](((state as unknown) as Record)[duckName]); } return duckSelectors; diff --git a/src/utils/polyfillSymbol.ts b/src/utils/polyfillSymbol.ts index c353f77c..f741b0c6 100644 --- a/src/utils/polyfillSymbol.ts +++ b/src/utils/polyfillSymbol.ts @@ -1,4 +1,4 @@ -function polyfillSymbol(name: string): void { +function polyfillSymbol(name: string) { if (!Symbol[name]) { Object.defineProperty(Symbol, name, { value: Symbol(name) }); } diff --git a/tests/hooks.test.ts b/tests/hooks.test.ts index 8b85ec03..1b8392a2 100644 --- a/tests/hooks.test.ts +++ b/tests/hooks.test.ts @@ -5,8 +5,8 @@ import { useObservable } from "src/hooks/useObservable"; describe("useDispatch", () => { const mockValue = { - dispatch: async (a: Action): Promise => a, - reducer: (): null => null, + dispatch: async (a: Action) => a, + reducer: () => null, state: null, subscribe: () => ({ closed: true, unsubscribe: () => undefined }), }; diff --git a/tests/index.mock.tsx b/tests/index.mock.tsx index db00faa8..253b020e 100644 --- a/tests/index.mock.tsx +++ b/tests/index.mock.tsx @@ -16,12 +16,12 @@ export function createMocks() { Record, string, unknown - > = () => (next) => (action): Promise => next(action); + > = () => (next) => (action) => next(action); const DECREMENT = "decrement"; const INCREMENT = "increment"; - const decrement = (state: number): number => state - 1; - const increment = jest.fn((state): number => state + 1); + const decrement = (state: number) => state - 1; + const increment = jest.fn((state: number) => state + 1); const counterReducer: (s: number, a?: Action) => number = ( state, action, @@ -39,17 +39,17 @@ export function createMocks() { initialState: 0, name: "counter", reducers: { [DECREMENT]: counterReducer, [INCREMENT]: counterReducer }, - selectors: { get: (state): number => state }, + selectors: { get: (state) => state }, }); const INIT = "init"; - const init = jest.fn((): boolean => true); + const init = jest.fn(() => true); const initDuck = createDuck({ actionMapping: { [ActionTypes.INIT]: INIT }, initialState: false, name: "init", reducers: { [INIT]: init }, - selectors: { get: (state): boolean => state }, + selectors: { get: (state) => state }, }); const dummyDuck = createDuck({ @@ -70,7 +70,7 @@ export function createMocks() { const RootProvider = createRootProvider(Context); - function Example(): React.ReactElement { + function Example() { const increment = useDispatch(counterDuck.actions.increment); const init = useSelector(rootDuck.selectors.init?.get); const count = useSelector(rootDuck.selectors.counter?.get, Context); @@ -86,7 +86,7 @@ export function createMocks() { const logger: Middleware, string, unknown> = ({ getState, - }) => (next) => async (action): Promise => { + }) => (next) => async (action) => { // eslint-disable-next-line no-console console.log("action to dispatch", action); // Call the next dispatch method in the middleware chain. @@ -110,7 +110,7 @@ export function createMocks() { unknown > = ({ dispatch }) => { dispatch({ type: "SOME_ACTION" }); - return () => async (action): Promise => action; + return () => async (action) => action; }; const emptyRootDuck = createRootDuck(); const ErrorContext = createContext( diff --git a/tests/index.test.tsx b/tests/index.test.tsx index f9ee7265..5ff01215 100644 --- a/tests/index.test.tsx +++ b/tests/index.test.tsx @@ -11,10 +11,9 @@ import { } from "src"; import { bindActionCreators } from "src/utils/bindActionCreators"; import { connect } from "src/utils/connect"; -// eslint-disable-next-line jest/no-mocks-import import { createMocks } from "./index.mock"; -describe("integration", (): void => { +describe("integration", () => { const { EnhancedContext, ErrorContext, @@ -112,9 +111,8 @@ describe("integration", (): void => { describe("createConnect", () => { const mapStateToProps = createStructuredSelector({ - count: rootDuck.selectors.counter?.get ?? ((): number => 0), - isInitialised: - rootDuck.selectors.init?.get ?? ((): boolean => false), + count: rootDuck.selectors.counter?.get ?? (() => 0), + isInitialised: rootDuck.selectors.init?.get ?? (() => false), }); const mapDispatchToProps = { increment: rootDuck.actions.counter.increment, @@ -262,7 +260,7 @@ describe("integration", (): void => { it("forwards ref to wrapped component", async () => { class ClassComponent extends React.PureComponent { - render(): React.ReactElement { + render() { return
; } } @@ -288,7 +286,7 @@ describe("integration", (): void => { .spyOn(console, "error") .mockImplementationOnce(() => undefined); class ClassComponent extends React.PureComponent { - render(): React.ReactElement { + render() { return
; } } @@ -318,7 +316,7 @@ describe("integration", (): void => { describe("contextSubscribe", () => { const listener = jest.fn(); - function Sample(): React.ReactElement { + function Sample() { const value = React.useContext(GlobalContext); React.useEffect( function contextSubscribe() { diff --git a/tsconfig.prod.json b/tsconfig.prod.json index 95d5accc..a3e05c83 100644 --- a/tsconfig.prod.json +++ b/tsconfig.prod.json @@ -1,4 +1,4 @@ { "extends": "./tsconfig.json", - "exclude": ["node_modules", "dist", "tests"] + "exclude": ["node_modules", "dist", "tests", "e2e"] }