From 82d9995f2bd55203e9f24d7890d7e504edff2fe9 Mon Sep 17 00:00:00 2001 From: Saturnino Abril Date: Fri, 5 Oct 2018 14:46:21 +0800 Subject: [PATCH] fix issue that blocks adding test for thread screen (#2221) --- .../markdown_code_block.js | 16 +- .../thread/__snapshots__/thread.test.js.snap | 147 ++++++++++++++++++ app/screens/thread/thread.js | 14 +- app/screens/thread/thread.test.js | 103 ++++++++++++ package.json | 5 +- test/setup.js | 10 ++ 6 files changed, 281 insertions(+), 14 deletions(-) create mode 100644 app/screens/thread/__snapshots__/thread.test.js.snap create mode 100644 app/screens/thread/thread.test.js diff --git a/app/components/markdown/markdown_code_block/markdown_code_block.js b/app/components/markdown/markdown_code_block/markdown_code_block.js index cea4808cb..f2341cf30 100644 --- a/app/components/markdown/markdown_code_block/markdown_code_block.js +++ b/app/components/markdown/markdown_code_block/markdown_code_block.js @@ -3,7 +3,7 @@ import {PropTypes} from 'prop-types'; import React from 'react'; -import {injectIntl, intlShape} from 'react-intl'; +import {intlShape} from 'react-intl'; import { Clipboard, StyleSheet, @@ -21,9 +21,8 @@ import mattermostManaged from 'app/mattermost_managed'; const MAX_LINES = 4; -class MarkdownCodeBlock extends React.PureComponent { +export default class MarkdownCodeBlock extends React.PureComponent { static propTypes = { - intl: intlShape.isRequired, navigator: PropTypes.object.isRequired, theme: PropTypes.object.isRequired, language: PropTypes.string, @@ -36,8 +35,13 @@ class MarkdownCodeBlock extends React.PureComponent { language: '', }; + static contextTypes = { + intl: intlShape, + }; + handlePress = preventDoubleTap(() => { - const {intl, navigator, theme} = this.props; + const {navigator, theme} = this.props; + const {intl} = this.context; const languageDisplayName = getDisplayNameForLanguage(this.props.language); let title; @@ -76,7 +80,7 @@ class MarkdownCodeBlock extends React.PureComponent { }); handleLongPress = async () => { - const {formatMessage} = this.props.intl; + const {formatMessage} = this.context.intl; const config = await mattermostManaged.getLocalConfig(); @@ -238,5 +242,3 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => { }, }; }); - -export default injectIntl(MarkdownCodeBlock); diff --git a/app/screens/thread/__snapshots__/thread.test.js.snap b/app/screens/thread/__snapshots__/thread.test.js.snap new file mode 100644 index 000000000..e78b7839e --- /dev/null +++ b/app/screens/thread/__snapshots__/thread.test.js.snap @@ -0,0 +1,147 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`thread should match snapshot, has root post 1`] = ` + + + + + + + +`; + +exports[`thread should match snapshot, no root post, loading 1`] = ` + + + + + + +`; + +exports[`thread should match snapshot, render footer 1`] = ` + +`; + +exports[`thread should match snapshot, render footer 2`] = `null`; + +exports[`thread should match snapshot, render footer 3`] = ` + +`; diff --git a/app/screens/thread/thread.js b/app/screens/thread/thread.js index 9c6d9d8e9..ee568d1b7 100644 --- a/app/screens/thread/thread.js +++ b/app/screens/thread/thread.js @@ -4,7 +4,7 @@ import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; import {Platform} from 'react-native'; -import {injectIntl, intlShape} from 'react-intl'; +import {intlShape} from 'react-intl'; import {General, RequestStatus} from 'mattermost-redux/constants'; import Loading from 'app/components/loading'; @@ -16,7 +16,7 @@ import StatusBar from 'app/components/status_bar'; import {makeStyleSheetFromTheme, setNavigatorStyles} from 'app/utils/theme'; import DeletedPost from 'app/components/deleted_post'; -class Thread extends PureComponent { +export default class Thread extends PureComponent { static propTypes = { actions: PropTypes.shape({ selectPost: PropTypes.func.isRequired, @@ -24,7 +24,6 @@ class Thread extends PureComponent { channelId: PropTypes.string.isRequired, channelType: PropTypes.string, displayName: PropTypes.string, - intl: intlShape.isRequired, navigator: PropTypes.object, myMember: PropTypes.object.isRequired, rootId: PropTypes.string.isRequired, @@ -36,8 +35,13 @@ class Thread extends PureComponent { state = {}; + static contextTypes = { + intl: intlShape, + }; + componentWillMount() { - const {channelType, displayName, intl} = this.props; + const {channelType, displayName} = this.props; + const {intl} = this.context; let title; if (channelType === General.DM_CHANNEL) { @@ -182,5 +186,3 @@ const getStyle = makeStyleSheetFromTheme((theme) => { }, }; }); - -export default injectIntl(Thread); diff --git a/app/screens/thread/thread.test.js b/app/screens/thread/thread.test.js new file mode 100644 index 000000000..9557f5693 --- /dev/null +++ b/app/screens/thread/thread.test.js @@ -0,0 +1,103 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; +import {shallow} from 'enzyme'; + +import Preferences from 'mattermost-redux/constants/preferences'; +import {General, RequestStatus} from 'mattermost-redux/constants'; + +import Thread from './thread.js'; + +jest.mock('react-intl'); + +describe('thread', () => { + const navigator = { + dismissModal: jest.fn(), + pop: jest.fn(), + resetTo: jest.fn(), + setTitle: jest.fn(), + }; + const baseProps = { + actions: { + selectPost: jest.fn(), + }, + channelId: 'channel_id', + channelType: General.OPEN_CHANNEL, + displayName: 'channel_display_name', + navigator, + myMember: {last_viewed_at: 0, user_id: 'member_user_id'}, + rootId: 'root_id', + theme: Preferences.THEMES.default, + postIds: ['root_id', 'post_id_1', 'post_id_2'], + channelIsArchived: false, + threadLoadingStatus: {status: RequestStatus.STARTED}, + }; + + test('should match snapshot, has root post', () => { + const wrapper = shallow( + , + {context: {intl: {formatMessage: jest.fn()}}}, + ); + expect(wrapper.getElement()).toMatchSnapshot(); + }); + + test('should match snapshot, no root post, loading', () => { + const newPostIds = ['post_id_1', 'post_id_2']; + const wrapper = shallow( + , + {context: {intl: {formatMessage: jest.fn()}}}, + ); + expect(wrapper.getElement()).toMatchSnapshot(); + }); + + test('should call props.navigator on onCloseChannel', () => { + const channelScreen = { + screen: 'Channel', + title: '', + animated: false, + backButtonTitle: '', + navigatorStyle: { + animated: true, + animationType: 'fade', + navBarHidden: true, + statusBarHidden: false, + statusBarHideWithNavBar: false, + screenBackgroundColor: 'transparent', + }, + }; + const newNavigator = {...navigator}; + const wrapper = shallow( + , + {context: {intl: {formatMessage: jest.fn()}}}, + ); + wrapper.instance().onCloseChannel(); + expect(newNavigator.resetTo).toHaveBeenCalledTimes(1); + expect(newNavigator.resetTo).toBeCalledWith(channelScreen); + }); + + test('should match snapshot, render footer', () => { + const wrapper = shallow( + , + {context: {intl: {formatMessage: jest.fn()}}}, + ); + + // return loading + expect(wrapper.instance().renderFooter()).toMatchSnapshot(); + + // return null + wrapper.setProps({threadLoadingStatus: {status: RequestStatus.SUCCESS}}); + expect(wrapper.instance().renderFooter()).toMatchSnapshot(); + + // return deleted post + const newPostIds = ['post_id_1', 'post_id_2']; + wrapper.setProps({postIds: newPostIds}); + expect(wrapper.instance().renderFooter()).toMatchSnapshot(); + }); +}); diff --git a/package.json b/package.json index 88798e15a..c1441a9eb 100644 --- a/package.json +++ b/package.json @@ -131,6 +131,9 @@ ], "moduleNameMapper": { "assets/images/video_player/(.*).png": "/dist/assets/images/video_player/$1@2x.png" - } + }, + "transformIgnorePatterns": [ + "node_modules/(?!react-native|jail-monkey)" + ] } } diff --git a/test/setup.js b/test/setup.js index 1484fe689..8c416b1dd 100644 --- a/test/setup.js +++ b/test/setup.js @@ -7,6 +7,16 @@ configure({adapter: new Adapter()}); /* eslint-disable no-console */ +jest.mock('NativeModules', () => { + return { + BlurAppScreen: () => true, + MattermostManaged: { + getConfig: jest.fn(), + }, + }; +}); +jest.mock('NativeEventEmitter'); + let logs; let warns; let errors;