From 68294fd3d23c7051d92900d07c64c467300636e0 Mon Sep 17 00:00:00 2001 From: Vyrtsev Mikhail Date: Sat, 20 Apr 2019 19:48:28 +0300 Subject: [PATCH 1/5] forbid dynamic type acquisition for typescript was useful during refactoring but makes no sense now --- web/tsconfig.json | 1 - 1 file changed, 1 deletion(-) diff --git a/web/tsconfig.json b/web/tsconfig.json index cb16d08f..7042615b 100644 --- a/web/tsconfig.json +++ b/web/tsconfig.json @@ -23,5 +23,4 @@ }, "include": ["app/**/*"], "exclude": ["node_modules"], - "typeAcquisition": { "enable": true } } From 7e84b356a2aed96b5482de0a34d2b516f52c4e90 Mon Sep 17 00:00:00 2001 From: Vyrtsev Mikhail Date: Sat, 20 Apr 2019 20:45:23 +0300 Subject: [PATCH 2/5] fix tests --- web/app/store/thread/reducers.test.ts | 10 ++++++---- web/app/testUtils/index.ts | 20 ++++++++++++++++++++ web/jest.config.js | 2 +- web/setup-jest-env.js | 1 - 4 files changed, 27 insertions(+), 6 deletions(-) delete mode 100644 web/setup-jest-env.js diff --git a/web/app/store/thread/reducers.test.ts b/web/app/store/thread/reducers.test.ts index b26e0926..d15530be 100644 --- a/web/app/store/thread/reducers.test.ts +++ b/web/app/store/thread/reducers.test.ts @@ -4,10 +4,10 @@ import { setCollapse } from './actions'; import { THREAD_SET_COLLAPSE } from './types'; describe('collapsedThreads', () => { - const comment = { id: 'some-id' } as Comment; - it('should set collapsed to true', () => { - const state = { collapsedThreads: {} }; + const comment = { id: 'some-id' } as Comment; + const node = { comment, replies: [] }; + const state = { collapsedThreads: {}, comments: [node] }; const dispatch = jest.fn(); const getState = jest.fn(() => state) as any; @@ -20,9 +20,11 @@ describe('collapsedThreads', () => { }); it('should collapse toggled', () => { + const comment = { id: 'some-id' } as Comment; + const node = { comment, replies: [] }; const dispatch = jest.fn(); const getState = jest.fn(); - getState.mockReturnValue({ collapsedThreads: { 'some-id': true } }); + getState.mockReturnValue({ collapsedThreads: { 'some-id': true }, comments: [node] }); setCollapse(comment.id)(dispatch, getState, undefined); expect(dispatch).toBeCalledWith({ diff --git a/web/app/testUtils/index.ts b/web/app/testUtils/index.ts index 5c9b588b..8f373dd0 100644 --- a/web/app/testUtils/index.ts +++ b/web/app/testUtils/index.ts @@ -1,3 +1,23 @@ +import { StaticStore } from '@app/common/static_store'; + +require('document-register-element/pony')(window); + +beforeEach(() => { + StaticStore.config = { + admin_email: 'admin@remark42.com', + admins: ['admin'], + auth_providers: ['dev', 'google'], + critical_score: -15, + low_score: -5, + edit_duration: 300, + max_comment_size: 3000, + max_image_size: 5000, + positive_score: false, + readonly_age: 100, + version: 'jest-test', + }; +}); + export function createDomContainer(setup: (domContainer: HTMLElement) => void): void { let domContainer: HTMLElement | null = null; beforeAll(() => { diff --git a/web/jest.config.js b/web/jest.config.js index 07cc975f..bb847d95 100644 --- a/web/jest.config.js +++ b/web/jest.config.js @@ -11,5 +11,5 @@ module.exports = { '\\.scss$': '/app/testUtils/mockStyles.js', '@app/(.*)': '/app/$1', }, - setupFilesAfterEnv: ['/setup-jest-env.js'], + setupFilesAfterEnv: ['/app/testUtils/index.ts'], }; diff --git a/web/setup-jest-env.js b/web/setup-jest-env.js deleted file mode 100644 index be67c9a2..00000000 --- a/web/setup-jest-env.js +++ /dev/null @@ -1 +0,0 @@ -require('document-register-element/pony')(window); From 38f9fd855c5ece3e1bf2505ea2bae9a09a9e9655 Mon Sep 17 00:00:00 2001 From: Vyrtsev Mikhail Date: Sat, 20 Apr 2019 20:02:01 +0300 Subject: [PATCH 3/5] fix #310: useless comment remains uncollapsed --- web/app/components/comment/connected-comment.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/app/components/comment/connected-comment.ts b/web/app/components/comment/connected-comment.ts index daf5f694..0648d2ac 100644 --- a/web/app/components/comment/connected-comment.ts +++ b/web/app/components/comment/connected-comment.ts @@ -22,6 +22,7 @@ import { blockUser, unblockUser, setVirifiedStatus } from '@app/store/user/actio import { Comment, Props } from './comment'; import { getCommentMode } from '@app/store/comments/getters'; import { uploadImage } from '@app/common/api'; +import { getThreadIsCollapsed } from '@app/store/thread/getters'; const mapProps = (state: StoreState, cprops: { data: CommentType }) => { const props: Pick< @@ -34,7 +35,7 @@ const mapProps = (state: StoreState, cprops: { data: CommentType }) => { post_info: state.info, isCommentsDisabled: state.info.read_only || false, theme: state.theme, - collapsed: state.collapsedThreads[cprops.data.id] === true, + collapsed: getThreadIsCollapsed(state, cprops.data), }; return props; }; From d1420286dd0a88ecff054103752b3f88428a954f Mon Sep 17 00:00:00 2001 From: Vyrtsev Mikhail Date: Sat, 20 Apr 2019 20:08:50 +0300 Subject: [PATCH 4/5] fix comment collapsing button works on second click on useless comment --- web/app/components/comment/comment.tsx | 4 ++-- web/app/components/comment/connected-comment.ts | 4 ++-- web/app/store/thread/actions.ts | 5 ++--- web/app/store/thread/reducers.test.ts | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/web/app/components/comment/comment.tsx b/web/app/components/comment/comment.tsx index 392c2eb1..1756c131 100644 --- a/web/app/components/comment/comment.tsx +++ b/web/app/components/comment/comment.tsx @@ -50,7 +50,7 @@ export interface Props { setReplyEditState?(id: CommentType['id'], mode: CommentMode): void; getPreview?: (text: string) => Promise; putCommentVote?(id: CommentType['id'], value: number): Promise; - collapseToggle?: (id: CommentType['id']) => void; + setCollapse?: (id: CommentType['id'], value: boolean) => void; setPinState?(id: CommentType['id'], value: boolean): Promise; blockUser?(id: User['id'], name: User['name'], ttl: BlockTTL): Promise; unblockUser?(id: User['id']): Promise; @@ -285,7 +285,7 @@ export class Comment extends Component { toggleCollapse() { this.props.setReplyEditState!(this.props.data.id, CommentMode.None); - this.props.collapseToggle!(this.props.data.id); + this.props.setCollapse!(this.props.data.id, !this.props.collapsed); } copyComment({ username, time }: { username: string; time: string }) { diff --git a/web/app/components/comment/connected-comment.ts b/web/app/components/comment/connected-comment.ts index 0648d2ac..ab0b3554 100644 --- a/web/app/components/comment/connected-comment.ts +++ b/web/app/components/comment/connected-comment.ts @@ -47,7 +47,7 @@ const mapDispatchToProps = (dispatch: StoreDispatch) => { | 'updateComment' | 'removeComment' | 'setReplyEditState' - | 'collapseToggle' + | 'setCollapse' | 'setPinState' | 'putCommentVote' | 'blockUser' @@ -59,7 +59,7 @@ const mapDispatchToProps = (dispatch: StoreDispatch) => { updateComment: (id: CommentType['id'], text: string) => dispatch(updateComment(id, text)), removeComment: (id: CommentType['id']) => dispatch(removeComment(id)), setReplyEditState: (id: CommentType['id'], mode: CommentMode) => dispatch(setCommentMode({ id, state: mode })), - collapseToggle: (id: CommentType['id']) => dispatch(setCollapse(id)), + setCollapse: (id: CommentType['id'], value: boolean) => dispatch(setCollapse(id, value)), setPinState: (id: CommentType['id'], value: boolean) => dispatch(setPinState(id, value)), putCommentVote: (id: CommentType['id'], value: number) => dispatch(putVote(id, value)), diff --git a/web/app/store/thread/actions.ts b/web/app/store/thread/actions.ts index 9fab8c1c..6faa5165 100644 --- a/web/app/store/thread/actions.ts +++ b/web/app/store/thread/actions.ts @@ -5,12 +5,11 @@ import { StoreAction } from '../index'; import { THREAD_SET_COLLAPSE } from './types'; import { saveCollapsedComments } from './utils'; -export const setCollapse = (id: Comment['id']): StoreAction => (dispatch, getState) => { - const collapsed = !getState().collapsedThreads[id]; +export const setCollapse = (id: Comment['id'], value: boolean): StoreAction => (dispatch, getState) => { dispatch({ type: THREAD_SET_COLLAPSE, id, - collapsed, + collapsed: value, }); saveCollapsedComments( siteId!, diff --git a/web/app/store/thread/reducers.test.ts b/web/app/store/thread/reducers.test.ts index d15530be..a606efb5 100644 --- a/web/app/store/thread/reducers.test.ts +++ b/web/app/store/thread/reducers.test.ts @@ -11,7 +11,7 @@ describe('collapsedThreads', () => { const dispatch = jest.fn(); const getState = jest.fn(() => state) as any; - setCollapse(comment.id)(dispatch, getState, undefined); + setCollapse(comment.id, true)(dispatch, getState, undefined); expect(dispatch).toBeCalledWith({ type: THREAD_SET_COLLAPSE, id: 'some-id', @@ -26,7 +26,7 @@ describe('collapsedThreads', () => { const getState = jest.fn(); getState.mockReturnValue({ collapsedThreads: { 'some-id': true }, comments: [node] }); - setCollapse(comment.id)(dispatch, getState, undefined); + setCollapse(comment.id, false)(dispatch, getState, undefined); expect(dispatch).toBeCalledWith({ type: THREAD_SET_COLLAPSE, id: 'some-id', From 22006bee81f67280c0fb622fc04be5503fc6caa2 Mon Sep 17 00:00:00 2001 From: Vyrtsev Mikhail Date: Sat, 20 Apr 2019 21:21:36 +0300 Subject: [PATCH 5/5] add logError: boolean param to fetcher Case for it is getUser api method. When user is not authenticated, api returns 403 error which pops up in console and have no meaning --- web/app/common/api.ts | 1 + web/app/common/fetcher.ts | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/web/app/common/api.ts b/web/app/common/api.ts index 68133ad0..dbe1b960 100644 --- a/web/app/common/api.ts +++ b/web/app/common/api.ts @@ -133,6 +133,7 @@ export const getUser = (): Promise => .get({ url: '/user', withCredentials: true, + logError: false, }) .catch(() => null); diff --git a/web/app/common/fetcher.ts b/web/app/common/fetcher.ts index 908bdd04..685467e7 100644 --- a/web/app/common/fetcher.ts +++ b/web/app/common/fetcher.ts @@ -10,6 +10,8 @@ interface FetcherInitBase { url: string; overriddenApiBase?: string; withCredentials?: boolean; + /** whether log error message to console */ + logError?: boolean; } interface FetcherInitJSON extends FetcherInitBase { @@ -34,6 +36,7 @@ const fetcher = methods.reduce>((acc, method) => { withCredentials = false, overriddenApiBase = API_BASE, contentType = 'application/json', + logError = true, } = typeof data === 'string' ? { url: data } : data; const basename = `${BASE_URL}${overriddenApiBase}`; @@ -81,8 +84,10 @@ const fetcher = methods.reduce>((acc, method) => { try { err = JSON.parse(text); } catch (e) { - // eslint-disable-next-line no-console - console.error(err); + if (logError) { + // eslint-disable-next-line no-console + console.error(err); + } throw 'Something went wrong.'; } throw err;