Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ module.exports = {
modules: true,
},
},
env: {
jest: true,
},
rules: {
'@typescript-eslint/no-parameter-properties': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
Expand Down
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ module.exports = {
watchPlugins: ['jest-watch-typeahead/filename', 'jest-watch-typeahead/testname'],
testEnvironment: 'jsdom',
resetMocks: true,
projects: ['src/utils/tests/jest.lint.js'],
};
11 changes: 10 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@
"scripts": {
"start": "react-native start",
"test": "jest",
"lint": "eslint src --ext .js,.ts,.tsx --no-ignore --max-warnings=0 && yarn ts:check",
"check-types": "tsc --project tsconfig.json",
"lint": "eslint src --ext .js,.ts,.tsx --no-ignore --max-warnings=0",
"format": "prettier --write --ignore-path .gitignore \"**/*.+(js|ts|tsx|json)\"",
"validate": "npm-run-all check-types lint test",
"lint-committed": "lint-committed",
"commit-formatting": "git commit -m \"Format files\" || echo \"No files to format\""
},
"jest-runner-eslint": {
"clipOptions": {
"ignorePath": "./.gitignore"
}
},
"dependencies": {
"@bam.tech/react-native-component-text-input": "^1.0.3",
"@martin_hotell/rex-tils": "^2.1.1",
Expand Down Expand Up @@ -58,11 +65,13 @@
"fetch-mock": "^7.3.3",
"husky": "3.1.0",
"jest": "^24.9.0",
"jest-runner-eslint": "0.7.5",
"jest-styled-components": "^6.3.3",
"jest-watch-typeahead": "0.4.2",
"jetifier": "^1.6.4",
"lint-committed": "0.0.0-development",
"metro-react-native-babel-preset": "^0.56.0",
"npm-run-all": "4.1.5",
"patch-package": "^6.1.2",
"prettier": "^1.16.4",
"react-dom": "^16.8.6",
Expand Down
4 changes: 2 additions & 2 deletions src/api/signup/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import wretch from 'wretch';

import { EMAIL_API_ENDPOINT } from '../config';

interface IValidateEmailParams {
interface ValidateEmailParams {
email: string;
}

export class SignUpApi {
public static subscribeNewsletter(subscribeNewsletterParams: IValidateEmailParams) {
public static subscribeNewsletter(subscribeNewsletterParams: ValidateEmailParams) {
return wretch()
.url(EMAIL_API_ENDPOINT)
.post(subscribeNewsletterParams)
Expand Down
5 changes: 3 additions & 2 deletions src/components/ButtonLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import { Button } from './Button';
import styled from 'styled-components/native';
import { NavigationScreenProps } from 'react-navigation';

interface IProps extends NavigationScreenProps {
interface Props extends NavigationScreenProps {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
navigationParams?: Record<string, any>;
route: string;
}

export const ButtonLink: FunctionComponent<IProps> = ({ route, navigation, navigationParams }) => (
export const ButtonLink: FunctionComponent<Props> = ({ route, navigation, navigationParams }) => (
<ButtonWithMargin title={route} onPress={() => navigation.navigate(route, navigationParams)} />
);

Expand Down
1 change: 0 additions & 1 deletion src/components/Toaster.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { FunctionComponent } from 'react';
//@ts-ignore
import ToasterMessage from 'react-native-toaster';
import { useSelector } from 'react-redux';

Expand Down
4 changes: 2 additions & 2 deletions src/modules/loading/reducer.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Reducer } from 'redux';

import { TLoadingState, LoadingActionTypes } from './types';
import { LoadingState, LoadingActionTypes } from './types';
import { TLoadingActionObjectTypes } from './actions';

export const loadingReducer: Reducer<TLoadingState, TLoadingActionObjectTypes> = (
export const loadingReducer: Reducer<LoadingState, TLoadingActionObjectTypes> = (
state = {},
action
) => {
Expand Down
4 changes: 2 additions & 2 deletions src/modules/loading/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import { call, put } from 'redux-saga/effects';
import { LoadingActions } from './actions';
import { LoaderName } from './types';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const addLoader = (saga: (...args: any[]) => any, loaderName: LoaderName) =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function*(...args: any[]): any {
try {
yield put(LoadingActions.showLoader(loaderName));
const result = yield call(saga, ...args);

return result;
} catch (error) {
throw error;
} finally {
yield put(LoadingActions.hideLoader(loaderName));
}
Expand Down
4 changes: 2 additions & 2 deletions src/modules/loading/selectors.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IAppState } from '../types';
import { AppState } from '../types';

import { LoaderName } from './types';

export const isLoadingSelector = (loaderName: LoaderName) => (state: IAppState) =>
export const isLoadingSelector = (loaderName: LoaderName) => (state: AppState) =>
state.loading[loaderName];
4 changes: 2 additions & 2 deletions src/modules/loading/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ export enum LoaderName {
Movies = 'Movies',
}

export type TLoadingState = { [name in LoaderName]?: boolean };
export type LoadingState = { [name in LoaderName]?: boolean };

export interface ILoadingProps {
export interface LoadingProps {
isLoading?: boolean;
}
6 changes: 3 additions & 3 deletions src/modules/movies/reducer.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Reducer } from 'redux';

import { TMoviesActionObjectTypes } from './actions';
import { IMoviesState, MoviesActionTypes } from './types';
import { MoviesState, MoviesActionTypes } from './types';

const initialMoviesState: IMoviesState = {
const initialMoviesState: MoviesState = {
movieList: undefined,
};

export const moviesReducer: Reducer<IMoviesState, TMoviesActionObjectTypes> = (
export const moviesReducer: Reducer<MoviesState, TMoviesActionObjectTypes> = (
state = initialMoviesState,
action
) => {
Expand Down
11 changes: 5 additions & 6 deletions src/modules/movies/sagas.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import { put, takeEvery, delay, call, all } from 'redux-saga/effects';
import { ActionsOfType } from '@martin_hotell/rex-tils';

import { MoviesActionTypes } from './types';
import { TMoviesActionObjectTypes, MoviesActions } from './actions';
import { MoviesActions } from './actions';
import { addLoader } from '../loading/sagas';
import { LoaderName } from '../loading/types';
import { MoviesApi } from '../../api/movies';

function* getMoviesSaga(
action: ActionsOfType<TMoviesActionObjectTypes, MoviesActionTypes.GET_MOVIES>
) {
function* getMoviesSaga() {
try {
// eslint-disable-next-line @typescript-eslint/unbound-method
const [movies] = yield all([call(MoviesApi.getMovies), delay(2000)]);
// delay is used here for testing purposes to demonstrate how to use jest timers
const movieTitles = movies.results.map(movie => movie.title);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const movieTitles = movies.results.map((movie: any) => movie.title);
yield put(MoviesActions.getMoviesSuccess(movieTitles));
} catch (err) {
console.log(err);
Expand Down
4 changes: 2 additions & 2 deletions src/modules/movies/selectors.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { IAppState } from '../types';
import { AppState } from '../types';

export const movieListSelector = (state: IAppState) => state.movies.movieList;
export const movieListSelector = (state: AppState) => state.movies.movieList;
2 changes: 1 addition & 1 deletion src/modules/movies/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ export enum MoviesActionTypes {
GET_MOVIES_SUCCESS = 'GET_MOVIES_SUCCESS',
}

export interface IMoviesState {
export interface MoviesState {
movieList?: string[];
}
10 changes: 8 additions & 2 deletions src/modules/reducer.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
import { ReducersMapObject, combineReducers } from 'redux';

import { IAppState } from './types';
import { AppState } from './types';
import { signupReducer } from './signup/reducer';
import { toasterReducer } from './toaster/reducer';
import { todoReducer } from './todos/reducer';
import { moviesReducer } from './movies/reducer';
import { loadingReducer } from './loading/reducer';

// TODO: fix typing
const reducers: ReducersMapObject = {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
//@ts-ignore
signup: signupReducer,
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
//@ts-ignore
toaster: toasterReducer,
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
//@ts-ignore
todos: todoReducer,
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
//@ts-ignore
movies: moviesReducer,
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
//@ts-ignore
loading: loadingReducer,
};

export const rootReducer = combineReducers<IAppState>(reducers);
export const rootReducer = combineReducers<AppState>(reducers);
3 changes: 1 addition & 2 deletions src/modules/signup/reducer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Reducer } from 'redux';

import { TSignUpActionObjectTypes } from './actions';
import { ISignupState } from './types';

export const signupReducer: Reducer<ISignupState, TSignUpActionObjectTypes> = (state = {}) => state;
export const signupReducer: Reducer<{}, TSignUpActionObjectTypes> = (state = {}) => state;
1 change: 1 addition & 0 deletions src/modules/signup/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ function* subscribeNewsletterSaga(
) {
try {
const { email } = action.payload;
// eslint-disable-next-line @typescript-eslint/unbound-method
yield call(SignUpApi.subscribeNewsletter, { email });
yield put(ToasterActions.showSuccessMessage(wording.subscriptionSuccessful));
} catch (err) {
Expand Down
2 changes: 0 additions & 2 deletions src/modules/signup/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
export enum SignUpActionTypes {
SUBSCRIBE_NEWSLETTER = 'SUBSCRIBE_NEWSLETTER',
}

export interface ISignupState {}
6 changes: 3 additions & 3 deletions src/modules/storeManager.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Store as ReduxStore } from 'redux';

import { IAppState } from '../modules/types';
import { AppState } from '../modules/types';

class StoreManager {
private _store?: ReduxStore<IAppState> = undefined;
private _store?: ReduxStore<AppState> = undefined;
private static _instance: StoreManager;

public static getInstance = () => {
Expand All @@ -14,7 +14,7 @@ class StoreManager {
return StoreManager._instance;
};

public set store(store: ReduxStore<IAppState>) {
public set store(store: ReduxStore<AppState>) {
this._store = store;
}
public get store() {
Expand Down
4 changes: 2 additions & 2 deletions src/modules/toaster/reducer.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Reducer } from 'redux';
import { IToasterState, ToasterActionTypes } from './types';
import { ToasterState, ToasterActionTypes } from './types';
import { TToasterActionObjectTypes } from './actions';

const initialState = null;

export const toasterReducer: Reducer<IToasterState | null, TToasterActionObjectTypes> = (
export const toasterReducer: Reducer<ToasterState | null, TToasterActionObjectTypes> = (
state = initialState,
action
) => {
Expand Down
4 changes: 2 additions & 2 deletions src/modules/toaster/selectors.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { IAppState } from '../types';
import { AppState } from '../types';

export const toasterMessageSelector = (state: IAppState) => state.toaster;
export const toasterMessageSelector = (state: AppState) => state.toaster;
2 changes: 1 addition & 1 deletion src/modules/toaster/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export enum ToasterActionTypes {
ADD_TOAST = 'ADD_TOAST',
}

export interface IToasterState {
export interface ToasterState {
text?: string;
duration?: number;
styles?: {
Expand Down
6 changes: 3 additions & 3 deletions src/modules/todos/reducer.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Reducer } from 'redux';

import { TTodoActionObjectTypes } from './actions';
import { ITodoState, TodoActionTypes } from './types';
import { TodoState, TodoActionTypes } from './types';

const initialTodoState: ITodoState = {
const initialTodoState: TodoState = {
todoList: [],
};

export const todoReducer: Reducer<ITodoState, TTodoActionObjectTypes> = (
export const todoReducer: Reducer<TodoState, TTodoActionObjectTypes> = (
state = initialTodoState,
action
) => {
Expand Down
4 changes: 2 additions & 2 deletions src/modules/todos/selectors.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { IAppState } from '../types';
import { AppState } from '../types';

export const todoListSelector = (state: IAppState) => state.todos.todoList;
export const todoListSelector = (state: AppState) => state.todos.todoList;
2 changes: 1 addition & 1 deletion src/modules/todos/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ export enum TodoActionTypes {
ADD_TODO = 'ADD_TODO',
}

export interface ITodoState {
export interface TodoState {
todoList: string[];
}
19 changes: 10 additions & 9 deletions src/modules/types.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { ISignupState } from './signup/types';
import { IToasterState } from './toaster/types';
import { ITodoState } from './todos/types';
import { IMoviesState } from './movies/types';
import { ToasterState } from './toaster/types';
import { TodoState } from './todos/types';
import { MoviesState } from './movies/types';
import { LoadingState } from './loading/types';

export interface IAppState {
signup: ISignupState;
toaster: IToasterState;
todos: ITodoState;
movies: IMoviesState;
export interface AppState {
signup: {};
toaster: ToasterState;
todos: TodoState;
movies: MoviesState;
loading: LoadingState;
}
2 changes: 1 addition & 1 deletion src/pages/About/About.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { FunctionComponent } from 'react';
import { Button } from '../../components/Button';
import { wording } from '../../utils/wording';
import { Container, Card, Title, Input } from '../../components/StyledComponents';
import { Container, Card, Title } from '../../components/StyledComponents';
import { NavigationScreenProps } from 'react-navigation';
import { Routes } from '../../navigation/routes';
import { Text } from 'react-native';
Expand Down
3 changes: 2 additions & 1 deletion src/pages/About/__tests__/About.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { fireEvent, debug } from 'react-native-testing-library';
import { fireEvent } from 'react-native-testing-library';
import 'jest-styled-components';

import { renderPage, getPropsWithNavigation } from '../../../utils/tests/helpers';
Expand All @@ -18,6 +18,7 @@ describe('[Page] About', () => {
// WHEN
fireEvent.press(NavigateSubscribeButton);
// THEN
// eslint-disable-next-line @typescript-eslint/unbound-method
expect(props.navigation.navigate).toHaveBeenCalledWith(Routes.Home);
});
});
Loading