-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Petr Juna
committed
Nov 7, 2019
1 parent
86cbee1
commit 25dfd7a
Showing
26 changed files
with
417 additions
and
24,583 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ node_js: | |
script: | ||
- npm run lint | ||
- npm run prettier:lint | ||
- npm run test:e2e | ||
- npm run build | ||
|
||
jobs: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { store } from '../src/test.pre'; | ||
import test from 'ava'; | ||
import { requestSignInAction, resetAuthAction } from '../src/auth/actions'; | ||
import { AuthSignInModel, AuthSuccessModel } from '@pyxismedia/lib-model'; | ||
|
||
test.serial.afterEach(() => { | ||
store.dispatch(resetAuthAction()); | ||
}); | ||
|
||
test.serial.cb('should authentificate user', t => { | ||
store.dispatch(requestSignInAction(new AuthSignInModel({ email: 'karel@vomacka.cz', password: '12345' }))); | ||
const unsubscribe = store.subscribe(() => { | ||
const state = store.getState(); | ||
t.log(state.auth); | ||
// Following props are unique so we don't know exact values | ||
t.truthy(state.auth.id); | ||
t.truthy(state.auth.createdAt); | ||
t.truthy(state.auth.token); | ||
// We know exact value | ||
t.is(state.auth.userId, AuthSuccessModel.MOCK.userId); | ||
// To kame sure that schema is not not providing redundant property | ||
// @ts-ignore | ||
t.falsy(state.auth._v); | ||
t.end(); | ||
unsubscribe(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
import { | ||
RequestPostsModel, | ||
PostModel, | ||
CreatePostModel, | ||
PostStateEnum, | ||
AuthSignInModel, | ||
DeletePostModel, | ||
} from '@pyxismedia/lib-model'; | ||
import postsEnJson from '@pyxismedia/lib-model/build/post/post.en-mock.json'; | ||
import test from 'ava'; | ||
import { | ||
requestPostsAction, | ||
resetPostAction, | ||
createPostAction, | ||
PostActions, | ||
deletePostAction, | ||
} from '../src/post/actions'; | ||
import { requestSignInAction, AuthActions, resetAuthAction } from '../src/auth/actions'; | ||
import { switchMap } from 'rxjs/operators'; | ||
import { resetToastAction, ToastActions } from '../src/toast/actions'; | ||
import { configureStore } from '../src/store'; | ||
import { Store } from 'redux'; | ||
import { Exception } from '../src/exception'; | ||
|
||
let store: Store; | ||
|
||
test.serial.beforeEach(() => { | ||
store = configureStore(); | ||
}); | ||
|
||
test.serial.afterEach(() => { | ||
store.dispatch(resetPostAction()); | ||
store.dispatch(resetAuthAction()); | ||
store.dispatch(resetToastAction()); | ||
}); | ||
|
||
test.serial.cb('should deliver posts without skipping', t => { | ||
store.dispatch(requestPostsAction(new RequestPostsModel(0))); | ||
const unsubscribe = store.subscribe(() => { | ||
t.deepEqual(store.getState().post.posts, { | ||
collection: (postsEnJson as unknown) as PostModel[], | ||
skip: 0, | ||
}); | ||
unsubscribe(); | ||
t.end(); | ||
}); | ||
}); | ||
|
||
test.serial.cb('should deliver posts and skip by 4', t => { | ||
const skip = 4; | ||
store.dispatch(requestPostsAction(new RequestPostsModel(skip))); | ||
const unsubscribe = store.subscribe(() => { | ||
const state = store.getState(); | ||
const collection = (postsEnJson.slice(4) as unknown) as PostModel[]; | ||
const expected = { | ||
collection, | ||
skip, | ||
}; | ||
t.deepEqual(state.post.posts, expected); | ||
unsubscribe(); | ||
t.end(); | ||
}); | ||
}); | ||
|
||
test.serial.cb('should deliver posts and skip by 3', t => { | ||
const skip = 3; | ||
store.dispatch(requestPostsAction(new RequestPostsModel(skip))); | ||
const unsubscribe = store.subscribe(() => { | ||
const state = store.getState(); | ||
const collection = (postsEnJson.slice(skip) as unknown) as PostModel[]; | ||
const expected = { | ||
collection, | ||
skip, | ||
}; | ||
t.deepEqual(state.post.posts, expected); | ||
unsubscribe(); | ||
t.end(); | ||
}); | ||
}); | ||
|
||
test.serial.cb('should respond with error for unaunthentificated user', t => { | ||
const post = new CreatePostModel( | ||
'Test 1', | ||
'Subtitle Test 1', | ||
'Lorem ispum', | ||
'#', | ||
PostStateEnum.DRAFT, | ||
['label 1'], | ||
// TODO: Does Author exists? If not it should raise issue | ||
'5d9e2c4974146800ea816336', | ||
// TODO: Does Author exists? If not it should raise issue | ||
'5d9e2c4974146800ea816336', | ||
); | ||
store.dispatch(createPostAction(post)); | ||
const unsubscribe = store.subscribe(() => { | ||
const state = store.getState(); | ||
if (state.toast) { | ||
t.deepEqual(state.action.type, 'CREATE_TOAST'); | ||
t.deepEqual(state.toast, { messages: [new Exception('Unauthorized', 401)] }); | ||
t.end(); | ||
} else { | ||
t.fail('Toast in store does not exist.'); | ||
} | ||
unsubscribe(); | ||
}); | ||
}); | ||
|
||
test.serial.cb('should create post and deliver it', t => { | ||
const post = new CreatePostModel( | ||
'Test 2', | ||
'Subtitle Test 2', | ||
'Lorem ispum', | ||
'#', | ||
PostStateEnum.DRAFT, | ||
['label 1'], | ||
// TODO: Does Author exists? If not it should raise issue | ||
'5d9e2c4974146800ea816336', | ||
// TODO: Does Author exists? If not it should raise issue | ||
'5d9e2c4974146800ea816336', | ||
); | ||
const signIn = new AuthSignInModel({ email: 'karel@vomacka.cz', password: '12345' }); | ||
//@ts-ignore | ||
store | ||
.dispatch(requestSignInAction(signIn)) | ||
//@ts-ignore | ||
.asActionObservable(AuthActions.DELIVER_SIGNIN) | ||
.pipe( | ||
//@ts-ignore | ||
switchMap(() => { | ||
//@ts-ignore | ||
return store.dispatch(createPostAction(post)).asActionObservable(PostActions.DELIVER_POST); | ||
}), | ||
) | ||
.subscribe(() => { | ||
const state = store.getState(); | ||
// t.log('STATE STATE STATE', state); | ||
const expected = { ...post }; | ||
if (state.post.post) { | ||
t.is(state.post.post.title, expected.title); | ||
t.is(state.post.post.subtitle, expected.subtitle); | ||
t.is(state.post.post.content, expected.content); | ||
t.is(state.post.post.image, expected.image); | ||
t.is(state.post.post.state, expected.state); | ||
t.deepEqual(state.post.post.labels, expected.labels); | ||
t.is(state.post.post.subtitle, expected.subtitle); | ||
t.is(state.post.post.createdBy, expected.createdBy); | ||
t.is(state.post.post.section, expected.section); | ||
console.log('id in test', state.post.post); | ||
store | ||
.dispatch(deletePostAction(new DeletePostModel(state.post.post.id))) | ||
//@ts-ignore | ||
.asActionObservable(ToastActions.CREATE_TOAST) | ||
.subscribe(() => { | ||
t.end(); | ||
}); | ||
} | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,12 @@ | ||
import { ActionType } from 'typesafe-actions'; | ||
import * as postActions from './post/actions'; | ||
import * as toastActions from './toast/actions'; | ||
import * as authActions from './auth/actions'; | ||
|
||
const actions = { | ||
...postActions, | ||
...toastActions, | ||
...authActions, | ||
}; | ||
|
||
export type ActionTypes = ActionType<typeof actions>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { AuthSignInModel, AuthSuccessModel } from '@pyxismedia/lib-model'; | ||
import { createAction } from 'typesafe-actions'; | ||
|
||
export enum AuthActions { | ||
REQUEST_SIGNIN = 'REQUEST_SIGNIN', | ||
DELIVER_SIGNIN = 'DELIVER_SIGNIN', | ||
RESET_SIGNIN = 'RESET_SIGNIN', | ||
} | ||
|
||
export const requestSignInAction = createAction(AuthActions.REQUEST_SIGNIN, action => (payload: AuthSignInModel) => | ||
action(payload), | ||
); | ||
|
||
export const deliverSignInAction = createAction(AuthActions.DELIVER_SIGNIN, action => (payload: AuthSuccessModel) => | ||
action(payload), | ||
); | ||
|
||
export const resetAuthAction = createAction(AuthActions.RESET_SIGNIN); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { RootEpic } from '../epics'; | ||
import { filter, switchMap, map, catchError } from 'rxjs/operators'; | ||
import { isActionOf, PayloadAction } from 'typesafe-actions'; | ||
import { requestSignInAction, AuthActions, deliverSignInAction } from './actions'; | ||
import { AuthSignInModel } from '../../../lib-model/src/auth/auth-signin.model'; | ||
import { API_AUTH } from '../constants'; | ||
import { AuthSuccessModel } from '../../../lib-model/src/auth/auth-success.model'; | ||
import { createToast } from '../toast/actions'; | ||
import { of } from 'rxjs'; | ||
|
||
export const requestSignInEpic: RootEpic = (action$, _$, { crud }) => | ||
action$.pipe( | ||
filter(isActionOf(requestSignInAction)), | ||
switchMap( | ||
({ payload }: PayloadAction<AuthActions.REQUEST_SIGNIN, AuthSignInModel>): Promise<AuthSuccessModel> => { | ||
return crud.post(API_AUTH, JSON.stringify(payload)); | ||
}, | ||
), | ||
map((auth: AuthSuccessModel) => { | ||
return deliverSignInAction(auth); | ||
}), | ||
catchError(error => { | ||
return of(createToast(error)); | ||
}), | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import * as authActions from './actions'; | ||
import { getType, ActionType } from 'typesafe-actions'; | ||
import { AuthSuccessModel } from '../../../lib-model/src/auth/auth-success.model'; | ||
|
||
export type AuthActionTypes = ActionType<typeof authActions>; | ||
|
||
export interface AuthState extends AuthSuccessModel {} | ||
|
||
export const initialState = { | ||
id: '', | ||
userId: '', | ||
token: '', | ||
}; | ||
|
||
export function authReducer(state: AuthState = initialState, action: AuthActionTypes): AuthState { | ||
switch (action.type) { | ||
case getType(authActions.deliverSignInAction): | ||
return { ...state, ...action.payload }; | ||
case getType(authActions.resetAuthAction): | ||
return { ...initialState }; | ||
case getType(authActions.requestSignInAction): | ||
default: | ||
return { ...state }; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,17 @@ | ||
import { combineEpics, Epic } from 'redux-observable'; | ||
import { requestPostsEpic, createPostEpic } from './post/epics'; | ||
import { requestPostsEpic, createPostEpic, deletePostEpic } from './post/epics'; | ||
import { ActionTypes } from './actions'; | ||
import { RootState } from './reducers'; | ||
import { Dependencies } from './middlewares'; | ||
import { requestSignInEpic } from './auth/epics'; | ||
import { createToastEpic } from './toast/epics'; | ||
|
||
export type RootEpic = Epic<ActionTypes, ActionTypes, RootState, Dependencies>; | ||
|
||
export const rootEpic = combineEpics(requestPostsEpic, createPostEpic); | ||
export const rootEpic = combineEpics( | ||
requestPostsEpic, | ||
createPostEpic, | ||
deletePostEpic, | ||
requestSignInEpic, | ||
createToastEpic, | ||
); |
Oops, something went wrong.