From 3f3d183ca3061c1f52f4a189b91d79c3a871760c Mon Sep 17 00:00:00 2001 From: Benjamin Piouffle Date: Wed, 7 Feb 2018 15:00:12 +1100 Subject: [PATCH 1/6] Fix typo in help --- app/assets/assets/help/fr/privacy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/assets/help/fr/privacy.md b/app/assets/assets/help/fr/privacy.md index 2605fa02f..017be16fa 100644 --- a/app/assets/assets/help/fr/privacy.md +++ b/app/assets/assets/help/fr/privacy.md @@ -2,7 +2,7 @@ Nous ne vendrons **jamais** vos données personelles et il n'y a pas grand chose toutes les façons : on ne collecte que ce dont on a besoin pour faire fonctionner le site. Vous devez par contre considérer toutes vos intéractions (votes, commentaires...) -comme **publiques**. Vous êtes libre d'utiliser votre vrai non ou juste un bon view +comme **publiques**. Vous êtes libre d'utiliser votre vrai nom ou juste un bon vieux pseudonyme si c'est ce que vous préférez. Bien que rien ne soit infaible, nous faisons attention à la sécurité et essayons de suivre les From 552ff3ba6a03211c8516262195fe7a3c5fd5df73 Mon Sep 17 00:00:00 2001 From: Benjamin Piouffle Date: Thu, 8 Feb 2018 09:10:00 +1100 Subject: [PATCH 2/6] Enforce strict redirect for Facebook oauth using state parameter --- app/components/Users/ThirdPartyAuthList.jsx | 2 +- app/components/Users/ThirdPartyCallback.jsx | 5 ++++- app/lib/third_party_auth.js | 5 +++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/components/Users/ThirdPartyAuthList.jsx b/app/components/Users/ThirdPartyAuthList.jsx index 4fa5dd3d0..ab8a3249e 100644 --- a/app/components/Users/ThirdPartyAuthList.jsx +++ b/app/components/Users/ThirdPartyAuthList.jsx @@ -10,7 +10,7 @@ const ThirdPartyAuthList = ({t, location: {query: {invitation_token}}}) => (

{t('actionWithThirdParty')}

- + diff --git a/app/components/Users/ThirdPartyCallback.jsx b/app/components/Users/ThirdPartyCallback.jsx index 021a96a5b..aa9c795f4 100644 --- a/app/components/Users/ThirdPartyCallback.jsx +++ b/app/components/Users/ThirdPartyCallback.jsx @@ -20,7 +20,10 @@ export default class ThirdPartyCallback extends React.PureComponent { if (!this.props.location.query.error) { this.props.login({ provider: this.props.params.provider, - params: this.props.location.query + params: { + code: this.props.location.query.code, + invitation_token: this.props.location.query.state + } }) } } diff --git a/app/lib/third_party_auth.js b/app/lib/third_party_auth.js index 5f06454e3..7a84bb1bf 100644 --- a/app/lib/third_party_auth.js +++ b/app/lib/third_party_auth.js @@ -5,7 +5,8 @@ import { optionsToQueryString } from './url_utils' export const facebookAuthUrl = callbackOptions => `https://www.facebook.com/v2.8/dialog/oauth${optionsToQueryString({ client_id: FB_APP_ID, - redirect_uri: `${FRONTEND_URL}/login/callback/facebook${optionsToQueryString(callbackOptions)}`, + redirect_uri: `${FRONTEND_URL}/login/callback/facebook`, response_type: 'code', - scope: "email,public_profile" + scope: "email,public_profile", + state: callbackOptions })}` From f9f86718acfee139bb1e5a780372c6b1b365aa8c Mon Sep 17 00:00:00 2001 From: Benjamin Piouffle Date: Thu, 15 Feb 2018 16:18:41 +1100 Subject: [PATCH 3/6] Minor typos and UI fixes --- app/assets/assets/locales/fr/errors.json | 2 +- app/components/Comments/CommentDisplay.jsx | 6 +++--- app/components/Comments/CommentsContainer.jsx | 2 +- app/styles/_components/App/sidebar.sass | 1 - 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/assets/assets/locales/fr/errors.json b/app/assets/assets/locales/fr/errors.json index 210a43cbc..f35a1ea07 100644 --- a/app/assets/assets/locales/fr/errors.json +++ b/app/assets/assets/locales/fr/errors.json @@ -14,7 +14,7 @@ "action_already_done": "Cette action a déjà été effectuée", "unauthenticated": "Vous devez vous connecter pour effectuer cette action", "unauthorized": "Merci de vous (re)connecter pour continuer", - "noInternet": "La connection au serveur a échoué, éssayez de rafraichir la page" + "noInternet": "La connection au serveur a échoué, essayez de rafraichir la page" }, "client": { "joinCrashed": "La connection au serveur a échouée", diff --git a/app/components/Comments/CommentDisplay.jsx b/app/components/Comments/CommentDisplay.jsx index 24043828e..d5484a579 100644 --- a/app/components/Comments/CommentDisplay.jsx +++ b/app/components/Comments/CommentDisplay.jsx @@ -143,10 +143,10 @@ export class CommentDisplay extends React.PureComponent { -
} - {(text || replyingTo) && + {text || (replyingTo && nesting > 6) &&
- {nesting > 6 && replyingTo && - @{replyingTo.username} + {(replyingTo && nesting > 6) && + @{replyingTo.username} } { text }
diff --git a/app/components/Comments/CommentsContainer.jsx b/app/components/Comments/CommentsContainer.jsx index e230f2e3c..32e079de9 100644 --- a/app/components/Comments/CommentsContainer.jsx +++ b/app/components/Comments/CommentsContainer.jsx @@ -31,7 +31,7 @@ export class CommentsContainer extends React.PureComponent { return (
{header &&
{header}
} - + {displayedComments.map(comment =>
diff --git a/app/styles/_components/App/sidebar.sass b/app/styles/_components/App/sidebar.sass index 466f06fa2..7b01aac79 100644 --- a/app/styles/_components/App/sidebar.sass +++ b/app/styles/_components/App/sidebar.sass @@ -1,7 +1,6 @@ $border-color: lightgrey #sidebar - @include animate(fadeIn, 0.5s) background: $white-bis overflow-y: auto overflow-x: hidden From be870d258f7ec2ca458ea9932a6b9fce0c7856d5 Mon Sep 17 00:00:00 2001 From: Benjamin Piouffle Date: Mon, 19 Feb 2018 12:23:48 +1100 Subject: [PATCH 4/6] Multiple UI improvements * Remove "in New Caledonia" on homepage as team is now dispatched * Show "Add to thread" instead of "Reply" on self comments * (French) Show "J'approuve" instead of "Confirmer" (it was error-prone for users) * Improve comment display * Improve comment form quoted reply display * Invert approve / refute columns and buttons positions * Use more neutral colors for presence indicators (primary + neutral) --- app/assets/assets/help/en/reputation.md | 3 +- app/assets/assets/help/fr/reputation.md | 6 +- app/assets/assets/locales/en/home.json | 2 +- app/assets/assets/locales/en/main.json | 1 + app/assets/assets/locales/en/videoDebate.json | 4 +- app/assets/assets/locales/fr/home.json | 2 +- app/assets/assets/locales/fr/main.json | 1 + app/assets/assets/locales/fr/videoDebate.json | 8 +- app/components/Comments/CommentDisplay.jsx | 185 +++++++++--------- app/components/Comments/CommentForm.jsx | 21 +- app/components/Comments/Vote.jsx | 23 +++ app/components/Statements/Statement.jsx | 12 +- app/components/Utils/CloseButton.jsx | 6 + app/components/Utils/Icon.jsx | 44 ++--- app/components/VideoDebate/Presence.jsx | 4 +- .../_components/VideoDebate/presence.sass | 2 + app/styles/_components/comments.sass | 71 +++---- 17 files changed, 206 insertions(+), 189 deletions(-) create mode 100644 app/components/Comments/Vote.jsx create mode 100644 app/components/Utils/CloseButton.jsx diff --git a/app/assets/assets/help/en/reputation.md b/app/assets/assets/help/en/reputation.md index 8339c7147..12464baba 100644 --- a/app/assets/assets/help/en/reputation.md +++ b/app/assets/assets/help/en/reputation.md @@ -16,8 +16,7 @@ These rules are subject to change, especially as the number of users grows. | Action | Reputation gain | |----------------------------------------------------------------|--------------------------| -| Your email is verified | +15pts -| You link your account to one of your social network's profile | +15pts +| Verify you email or link a third-party account | +15pts | One of your comments is voted up | +2pts | One of your sourced comment is voted up | +3pts | Someone approves one of your modifications in history | +5pts diff --git a/app/assets/assets/help/fr/reputation.md b/app/assets/assets/help/fr/reputation.md index cfd393595..a7487cb20 100644 --- a/app/assets/assets/help/fr/reputation.md +++ b/app/assets/assets/help/fr/reputation.md @@ -12,15 +12,15 @@ Gagner en réputation vous permet de débloquer des nouveaux [privilèges](/help/privileges). Vous pouvez gagner jusqu'à 25 points de réputation par jour (les compteurs sont réinitialisés à minuit). -Ces règles sont sujettes à évolution dans le temps. +Ces règles sont sujettes à évolution dans le temps, en particulier avec la +montée du nombre d'utilisateurs. # Pour gagner de la réputation | Action | Gain | |----------------------------------------------------------------|------------------| -| Faire vérifier son email | +15pts -| Relier au moins un compte tierce (Facebook) | +15pts +| Vérifier son email ou relier un compte tierce (Facebook) | +15pts | Un de vos commentaires recoit un vote positif | +2pts | Un de vos commentaires **sourcé** recoit un vote positif | +3pts | Quelqu'un approuve une de vos modifications dans l'historique | +5pts diff --git a/app/assets/assets/locales/en/home.json b/app/assets/assets/locales/en/home.json index fd478cead..702e609dc 100644 --- a/app/assets/assets/locales/en/home.json +++ b/app/assets/assets/locales/en/home.json @@ -9,7 +9,7 @@ "creatingAnAccount": "creating an account", "invitation": "Ask for an invitation", "inviteFriend": "Invite a friend", - "footer": "Created with {{iconLove}} in New Caledonia using ", + "footer": "Created with {{iconLove}} using ", "emailPlaceholder": "Email address", "inviteSuccess": "Invitation request confirmed !", "error_invalid_email": "Invalid email address" diff --git a/app/assets/assets/locales/en/main.json b/app/assets/assets/locales/en/main.json index e29e14be9..691611177 100644 --- a/app/assets/assets/locales/en/main.json +++ b/app/assets/assets/locales/en/main.json @@ -35,6 +35,7 @@ "remove": "Remove", "delete": "Delete", "reply": "Reply", + "addToThread": "Add to thread", "approve": "Approve", "refute": "Refute", "edit": "Edit", diff --git a/app/assets/assets/locales/en/videoDebate.json b/app/assets/assets/locales/en/videoDebate.json index e04aadb9a..9ae036e26 100644 --- a/app/assets/assets/locales/en/videoDebate.json +++ b/app/assets/assets/locales/en/videoDebate.json @@ -23,8 +23,8 @@ "loadMore_replies": "Load more replies ({{count}})", "loadMore_comments": "Load more comments ({{count}})", "replyingTo": "Replying to", - "approve": "Confirm", - "approve_reply": "Confirm this comment", + "approve": "Approve", + "approve_reply": "Approve this comment", "refute": "Refute", "refute_reply": "Refute this comment", "revealForm": "Add a source or comment" diff --git a/app/assets/assets/locales/fr/home.json b/app/assets/assets/locales/fr/home.json index 1d85cd27c..f3514f02b 100644 --- a/app/assets/assets/locales/fr/home.json +++ b/app/assets/assets/locales/fr/home.json @@ -9,7 +9,7 @@ "creatingAnAccount": "créant un compte", "invitation": "Demander une invitation", "inviteFriend": "Inviter un ami", - "footer": "Créé avec {{iconLove}} en Nouvelle-Calédonie à l'aide d'", + "footer": "Créé avec {{iconLove}} à l'aide d'", "emailPlaceholder": "Adresse email", "inviteSuccess": "Demande d'invitation enregistrée !", "error_invalid_email": "Adresse email invalide" diff --git a/app/assets/assets/locales/fr/main.json b/app/assets/assets/locales/fr/main.json index 3674ca2d1..8365403bf 100644 --- a/app/assets/assets/locales/fr/main.json +++ b/app/assets/assets/locales/fr/main.json @@ -34,6 +34,7 @@ "remove": "Retirer", "delete": "Supprimer", "reply": "Répondre", + "addToThread": "Ajouter à la suite", "approve": "Confirmer", "refute": "Réfuter", "edit": "Éditer", diff --git a/app/assets/assets/locales/fr/videoDebate.json b/app/assets/assets/locales/fr/videoDebate.json index 7b96427cd..991dd4664 100644 --- a/app/assets/assets/locales/fr/videoDebate.json +++ b/app/assets/assets/locales/fr/videoDebate.json @@ -23,10 +23,10 @@ "loadMore_replies": "Charger plus de réponses ({{count}})", "loadMore_comments": "Charger plus de commentaires ({{count}})", "replyingTo": "En réponse à", - "approve": "Confirmer", - "approve_reply": "Confirmer ce commentaire", - "refute": "Réfuter", - "refute_reply": "Réfuter ce commentaire", + "approve": "J'approuve", + "approve_reply": "J'approuve ce commentaire", + "refute": "Je réfute", + "refute_reply": "Je réfute ce commentaire", "revealForm": "Ajouter une source ou un commentaire" }, "video": { diff --git a/app/components/Comments/CommentDisplay.jsx b/app/components/Comments/CommentDisplay.jsx index d5484a579..0c7f599cc 100644 --- a/app/components/Comments/CommentDisplay.jsx +++ b/app/components/Comments/CommentDisplay.jsx @@ -19,8 +19,13 @@ import {flashErrorUnauthenticated} from '../../state/flashes/reducer' import UserPicture from '../Users/UserPicture' import { USER_PICTURE_SMALL } from '../../constants' import MediaLayout from '../Utils/MediaLayout' +import Vote from './Vote' +// TODO Use ReputationGuard to protect actions +// Add the following possibilities to reputationGuard : +// onUnauthorized = "hide" | "showMessage" | "flash" + @connect(({CurrentUser, VideoDebate}, props) => ({ currentUser: CurrentUser.data, myVote: VideoDebate.comments.voted.get(props.comment.id, 0), @@ -36,27 +41,97 @@ export class CommentDisplay extends React.PureComponent { this.showRepliesToggle = this.showRepliesToggle.bind(this) // Authenticated actions - this.vote = this.actionAuthenticated(this.vote.bind(this)) this.actionReply = this.actionAuthenticated(this.actionReply.bind(this)) this.handleFlag = this.actionAuthenticated(this.handleFlag.bind(this)) } - getRemoveOrFlag() { - const { currentUser, comment, isFlagged, t } = this.props - if (currentUser.id === comment.user.id) - return ( - - - {t('actions.delete')} - - ) - else return ( - + render() { + const { user, text, source, score, inserted_at, approve } = this.props.comment + const { t, withoutActions, withoutHeader, replyingTo, nesting, replies, myVote, isVoting, hideThread, className, richMedias=true } = this.props + const approveClass = approve !== null && (approve ? 'approve' : 'refute') + const isOwnComment = this.props.comment.user.id === this.props.currentUser.id + + return ( + + ) + } + + renderOwnCommentActions() { + return [ + + + {this.props.t('actions.addToThread')} + , + + + {this.props.t('actions.delete')} + + ] + } + + renderOtherCommentActions() { + return [ + + + {this.props.t('actions.reply')} + , + - {t(isFlagged ? 'actions.flagged' : 'actions.flag')} + {this.props.t(this.props.isFlagged ? 'actions.flagged' : 'actions.flag')} - ) + ] } handleDelete() { @@ -95,10 +170,6 @@ export class CommentDisplay extends React.PureComponent { } } - vote(value) { - this.props.commentVote({comment: this.props.comment, value}) - } - showRepliesToggle() { this.setState({showReplies: !this.state.showReplies}) } @@ -107,80 +178,4 @@ export class CommentDisplay extends React.PureComponent { const formName = `formAddComment-${this.props.comment.statement_id}` this.props.change(formName, 'reply_to', this.props.comment) } - - render() { - const { user, text, source, score, inserted_at, approve } = this.props.comment - const { t, withoutActions, withoutHeader, replyingTo, nesting, replies, myVote, isVoting, hideThread, className, richMedias=true } = this.props - const approveClass = approve !== null && (approve ? 'approve' : 'refute') - return ( -
- - {!withoutActions && -
- 0 })} - onClick={() => myVote <= 0 ? this.vote(1) : this.vote(0)}/> -
- {isVoting ? : score} -
- myVote >= 0 ? this.vote(-1) : this.vote(0)}/> -
- } - - } - content={ -
-
- {!withoutHeader &&
- - - - - -
} - {text || (replyingTo && nesting > 6) && -
- {(replyingTo && nesting > 6) && - @{replyingTo.username} - } - { text } -
- } - {source && } -
- {!withoutActions && - - } -
- } - /> - {!hideThread && replies && - - } -
- ) - } } diff --git a/app/components/Comments/CommentForm.jsx b/app/components/Comments/CommentForm.jsx index e8f88c1b3..7d5810066 100644 --- a/app/components/Comments/CommentForm.jsx +++ b/app/components/Comments/CommentForm.jsx @@ -9,7 +9,8 @@ import { withRouter } from 'react-router' import { renderField, validateLength, cleanStrMultiline } from "../FormUtils" import { COMMENT_LENGTH, USER_PICTURE_LARGE } from "../../constants" import TextareaAutosize from "../FormUtils/TextareaAutosize" -import { Icon } from '../Utils/Icon' +import CloseButton from '../Utils/CloseButton' +import Icon from '../Utils/Icon' import Tag from '../Utils/Tag' import UserAppellation from '../Users/UserAppellation' import { postComment } from '../../state/video_debate/comments/effects' @@ -92,16 +93,16 @@ export class CommentForm extends React.PureComponent {
{formValues && formValues.reply_to &&
- this.props.change('reply_to', null)}> - + + this.props.change('reply_to', null)}/> {t('comment.replyingTo')}  - +
} @@ -137,13 +138,13 @@ export class CommentForm extends React.PureComponent { , - , , + ]) } diff --git a/app/components/Comments/Vote.jsx b/app/components/Comments/Vote.jsx new file mode 100644 index 000000000..11be7adac --- /dev/null +++ b/app/components/Comments/Vote.jsx @@ -0,0 +1,23 @@ +import React from 'react' +import classNames from 'classnames' + +import { Icon } from '../Utils' + + +const Vote = ({isVoting, score, myVote, onVote}) => ( +
+
+ 0 })} + onClick={() => myVote <= 0 ? onVote(1) : onVote(0)}/> +
+ {isVoting ? : score} +
+ myVote >= 0 ? onVote(-1) : onVote(0)}/> +
+
+) + +export default Vote \ No newline at end of file diff --git a/app/components/Statements/Statement.jsx b/app/components/Statements/Statement.jsx index a1fcf1b0e..dc4781869 100644 --- a/app/components/Statements/Statement.jsx +++ b/app/components/Statements/Statement.jsx @@ -151,22 +151,22 @@ export class Statement extends React.PureComponent { renderFactsAndComments() { if (this.props.commentsLoading) return () - const { statement, comments, approvingFacts, refutingFacts, currentUser, isAuthenticated } = this.props + const { statement, comments, approvingFacts, refutingFacts } = this.props return (
{(approvingFacts.size > 0 || refutingFacts.size > 0) &&
- {approvingFacts.size > 0 && - - } {refutingFacts.size > 0 && } + {approvingFacts.size > 0 && + + }
}
diff --git a/app/components/Utils/CloseButton.jsx b/app/components/Utils/CloseButton.jsx new file mode 100644 index 000000000..670112ef4 --- /dev/null +++ b/app/components/Utils/CloseButton.jsx @@ -0,0 +1,6 @@ +import React from 'react' + +const CloseButton = ({onClick}) => + + +export default CloseButton \ No newline at end of file diff --git a/app/components/Utils/Icon.jsx b/app/components/Utils/Icon.jsx index bbaa13d42..02cddc7e7 100644 --- a/app/components/Utils/Icon.jsx +++ b/app/components/Utils/Icon.jsx @@ -1,36 +1,20 @@ import React from "react" +import classNames from 'classnames' -export class Icon extends React.PureComponent { - constructor(props) { - super(props) - } - renderIcon(name) { - return () - } +export const Icon = ({name, size, withContainer=true, className, isClickable, ...otherProps}) => { + const sizeClass = size && `is-${size}` + const icon = - render() { - const {name, size, withContainer, className, isClickable, ...otherProps} = this.props - const sizeClass = size ? ` is-${size} ` : ' ' - if (withContainer) - if (isClickable) return ( - - {this.renderIcon(name)} - - ) - else return ( - - {this.renderIcon(name)} - - ) - else return this.renderIcon(name) - } -} + if (!withContainer) + return icon -Icon.defaultProps = { - withContainer: true, - isClickable: false, - size: "", - name: "question", - className: '' + const Container = isClickable ? 'a' : 'span' + return ( + + {icon} + + ) } + +export default Icon \ No newline at end of file diff --git a/app/components/VideoDebate/Presence.jsx b/app/components/VideoDebate/Presence.jsx index 37c58cc19..c0bca5cbf 100644 --- a/app/components/VideoDebate/Presence.jsx +++ b/app/components/VideoDebate/Presence.jsx @@ -8,11 +8,11 @@ import Tag from '../Utils/Tag' const Presence = ({t, nbUsers, nbViewers}) =>
- + {t('presence.user', {count: nbUsers})} - + {t('presence.viewer', {count: nbViewers})} diff --git a/app/styles/_components/VideoDebate/presence.sass b/app/styles/_components/VideoDebate/presence.sass index 3e1728eb0..c5a89439b 100644 --- a/app/styles/_components/VideoDebate/presence.sass +++ b/app/styles/_components/VideoDebate/presence.sass @@ -4,5 +4,7 @@ border-radius: 0.2em font-size: 0.8em float: right + &.viewers + border: 1px solid $grey-lighter .icon margin-right: 0.25em \ No newline at end of file diff --git a/app/styles/_components/comments.sass b/app/styles/_components/comments.sass index 6c42edd91..216a966c3 100644 --- a/app/styles/_components/comments.sass +++ b/app/styles/_components/comments.sass @@ -15,6 +15,8 @@ $max-comment-width: 600px .reply_to margin-bottom: 5px + .delete + margin-right: 0.5em .control .textarea $commentboxSize: 60px @@ -68,16 +70,18 @@ $max-comment-width: 600px color: grey .media.comment - padding: 0.1em 0 border-top: none width: 100% &:not(:last-child) margin: 0 &.isBlurred filter: blur(2px) - &.quoted .comment-text + &.quoted font-style: italic - color: grey + color: $grey + border-left: 0.25em solid $grey-lighter + padding-left: 0.5em + margin-left: 0.5em .user-picture margin-right: 0.25em .media-left @@ -114,25 +118,6 @@ $max-comment-width: 600px .comment-time font-size: 11px color: #949494 - .comment-text - white-space: pre-wrap - word-wrap: break-word - background-color: $white - padding: 0.5em 1em - border: 1px solid $grey-lighter - border-radius: 0 0.5em 0.5em 0.5em - display: inline-block - +tablet - &:before - width: 0 - height: 0 - border-left: 8px solid transparent - border-right: 8px solid transparent - border-bottom: 8px solid white - position: absolute - left: 0.35em - margin-top: -1em - content: '' .media-content overflow: hidden max-width: $max-comment-width @@ -173,21 +158,41 @@ $max-comment-width: 600px &:hover text-decoration: underline text-decoration-color: $grey-light - .comment-actions > a - font-size: 11px - color: $grey-light - margin-right: 15px - &:hover - color: darken(#c7c7c7, 25) - text-decoration: underline - &> .icon - font-size: 10px - vertical-align: middle - width: 10px .action-report.selected color: $red pointer-events: none +.media.comment:not(.quoted) .comment-text + white-space: pre-wrap + word-wrap: break-word + background-color: $white + padding: 0.4em 0.7em + border: 1px solid $grey-lighter + border-radius: 0 0.5em 0.5em 0.5em + display: inline-block + +tablet + &:before + width: 0 + height: 0 + border-left: 8px solid transparent + border-right: 8px solid transparent + border-bottom: 8px solid white + position: absolute + left: 0.35em + margin-top: -0.9em + content: '' + +.comment-actions a + font-size: 0.8em + color: $grey-light + margin-right: 1em + &:hover + color: darken(#c7c7c7, 25) + text-decoration: underline + &> .icon + font-size: 0.8em + vertical-align: middle + .comments-list width: 100% padding: 10px From fb556acd867b86cf3538a8a2b2b927219cecb6ff Mon Sep 17 00:00:00 2001 From: Benjamin Piouffle Date: Mon, 19 Feb 2018 14:55:32 +1100 Subject: [PATCH 5/6] Add some snapshot tests --- app/components/Users/SignupForm.jsx | 6 +-- app/components/Utils/ErrorView.jsx | 5 +- app/components/Utils/Message.jsx | 4 +- app/components/Utils/__tests__/Icon.spec.jsx | 21 ++++++++ .../Utils/__tests__/Message.spec.jsx | 17 ++++++ .../Utils/__tests__/Notification.spec.jsx | 17 ++++++ app/components/Utils/__tests__/Tag.spec.jsx | 9 ++++ .../__snapshots__/Icon.spec.jsx.snap | 48 +++++++++++++++++ .../__snapshots__/Message.spec.jsx.snap | 52 +++++++++++++++++++ .../__snapshots__/Notification.spec.jsx.snap | 32 ++++++++++++ .../__tests__/__snapshots__/Tag.spec.jsx.snap | 17 ++++++ package.json | 18 ++++++- tests_setup.js | 17 ++++++ 13 files changed, 253 insertions(+), 10 deletions(-) create mode 100644 app/components/Utils/__tests__/Icon.spec.jsx create mode 100644 app/components/Utils/__tests__/Message.spec.jsx create mode 100644 app/components/Utils/__tests__/Notification.spec.jsx create mode 100644 app/components/Utils/__tests__/Tag.spec.jsx create mode 100644 app/components/Utils/__tests__/__snapshots__/Icon.spec.jsx.snap create mode 100644 app/components/Utils/__tests__/__snapshots__/Message.spec.jsx.snap create mode 100644 app/components/Utils/__tests__/__snapshots__/Notification.spec.jsx.snap create mode 100644 app/components/Utils/__tests__/__snapshots__/Tag.spec.jsx.snap create mode 100644 tests_setup.js diff --git a/app/components/Users/SignupForm.jsx b/app/components/Users/SignupForm.jsx index 51a7c6b9e..b4a065c9a 100644 --- a/app/components/Users/SignupForm.jsx +++ b/app/components/Users/SignupForm.jsx @@ -27,15 +27,13 @@ const SignupForm = ({location, t}) => {
{t('invitationOnlyBody')}
- } - /> +
) } diff --git a/app/components/Utils/ErrorView.jsx b/app/components/Utils/ErrorView.jsx index 61a064d4a..6a07df13a 100644 --- a/app/components/Utils/ErrorView.jsx +++ b/app/components/Utils/ErrorView.jsx @@ -33,8 +33,7 @@ export class ErrorView extends React.PureComponent {
{t('title')}

} - body={ + header={

{t('title')}

}>

{tError(t, error)}{this.getMoreInfo()}

{(canGoBack || canReload) &&
} @@ -48,7 +47,7 @@ export class ErrorView extends React.PureComponent { {t('main:actions.reload')} }
- } +
/>
) diff --git a/app/components/Utils/Message.jsx b/app/components/Utils/Message.jsx index a6b4c62b4..d4ef75b1d 100644 --- a/app/components/Utils/Message.jsx +++ b/app/components/Utils/Message.jsx @@ -1,13 +1,13 @@ import React from 'react' -const Message = ({type='info', header='', body=''}) => +const Message = ({type='info', header='', children}) =>
{header &&
{header}
}
- {body} + {children}
diff --git a/app/components/Utils/__tests__/Icon.spec.jsx b/app/components/Utils/__tests__/Icon.spec.jsx new file mode 100644 index 000000000..57e6107e8 --- /dev/null +++ b/app/components/Utils/__tests__/Icon.spec.jsx @@ -0,0 +1,21 @@ +import Icon from '../Icon' + +test("render icon", () => { + snapshot() +}) + +test("set size", () => { + snapshot() +}) + +test("render without container", () => { + snapshot() +}) + +test("use 'a' if is link", () => { + snapshot() +}) + +test("other props get passed to container", () => { + snapshot() +}) \ No newline at end of file diff --git a/app/components/Utils/__tests__/Message.spec.jsx b/app/components/Utils/__tests__/Message.spec.jsx new file mode 100644 index 000000000..e77ce348c --- /dev/null +++ b/app/components/Utils/__tests__/Message.spec.jsx @@ -0,0 +1,17 @@ +import Message from '../Message' + +test("render message", () => { + snapshot(Hello) +}) + +test("can set type", () => { + snapshot(Alert !) +}) + +test("can set header", () => { + snapshot(Hellooow) +}) + +test("without body", () => { + snapshot() +}) diff --git a/app/components/Utils/__tests__/Notification.spec.jsx b/app/components/Utils/__tests__/Notification.spec.jsx new file mode 100644 index 000000000..5b4d8d3a5 --- /dev/null +++ b/app/components/Utils/__tests__/Notification.spec.jsx @@ -0,0 +1,17 @@ +import Notification from '../Notification' + +test("render message", () => { + snapshot(Hello) +}) + +test("can set type", () => { + snapshot(Alert !) +}) + +test("pass props", () => { + snapshot(Hellooow) +}) + +test("without body", () => { + snapshot() +}) diff --git a/app/components/Utils/__tests__/Tag.spec.jsx b/app/components/Utils/__tests__/Tag.spec.jsx new file mode 100644 index 000000000..75698844e --- /dev/null +++ b/app/components/Utils/__tests__/Tag.spec.jsx @@ -0,0 +1,9 @@ +import Tag from '../Tag' + +test("render tag", () => { + snapshot(Test) +}) + +test("set size", () => { + snapshot(Test) +}) diff --git a/app/components/Utils/__tests__/__snapshots__/Icon.spec.jsx.snap b/app/components/Utils/__tests__/__snapshots__/Icon.spec.jsx.snap new file mode 100644 index 000000000..542c89b21 --- /dev/null +++ b/app/components/Utils/__tests__/__snapshots__/Icon.spec.jsx.snap @@ -0,0 +1,48 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`other props get passed to container 1`] = ` + + + +`; + +exports[`render icon 1`] = ` + + + +`; + +exports[`render without container 1`] = ` + +`; + +exports[`set size 1`] = ` + + + +`; + +exports[`use 'a' if is link 1`] = ` + + + +`; diff --git a/app/components/Utils/__tests__/__snapshots__/Message.spec.jsx.snap b/app/components/Utils/__tests__/__snapshots__/Message.spec.jsx.snap new file mode 100644 index 000000000..a100c6dc3 --- /dev/null +++ b/app/components/Utils/__tests__/__snapshots__/Message.spec.jsx.snap @@ -0,0 +1,52 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`can set header 1`] = ` +
+
+ Awesome title +
+
+ Hellooow +
+
+`; + +exports[`can set type 1`] = ` +
+
+ Alert ! +
+
+`; + +exports[`render message 1`] = ` +
+
+ Hello +
+
+`; + +exports[`without body 1`] = ` +
+
+
+`; diff --git a/app/components/Utils/__tests__/__snapshots__/Notification.spec.jsx.snap b/app/components/Utils/__tests__/__snapshots__/Notification.spec.jsx.snap new file mode 100644 index 000000000..5af2ae614 --- /dev/null +++ b/app/components/Utils/__tests__/__snapshots__/Notification.spec.jsx.snap @@ -0,0 +1,32 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`can set type 1`] = ` +
+ Alert ! +
+`; + +exports[`pass props 1`] = ` +
+ Hellooow +
+`; + +exports[`render message 1`] = ` +
+ Hello +
+`; + +exports[`without body 1`] = ` +
+`; diff --git a/app/components/Utils/__tests__/__snapshots__/Tag.spec.jsx.snap b/app/components/Utils/__tests__/__snapshots__/Tag.spec.jsx.snap new file mode 100644 index 000000000..985d1e6ed --- /dev/null +++ b/app/components/Utils/__tests__/__snapshots__/Tag.spec.jsx.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`render tag 1`] = ` +
+ Test +
+`; + +exports[`set size 1`] = ` +
+ Test +
+`; diff --git a/package.json b/package.json index 3ea1c595a..f476f5143 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,20 @@ "serve": "brunch watch --server -n", "watch": "jest --watch", "test": "jest", - "coverage": "jest --coverage '--collectCoverageFrom=app/+(API|lib|state)/**/!(record).{js,jsx}'" + "wtest": "jest --watch", + "coverage": "jest --coverage '--collectCoverageFrom=app/+(API|components|lib|state)/**/!(record).{js,jsx}'" + }, + "jest": { + "setupFiles": [ + "./tests_setup.js" + ], + "snapshotSerializers": [ + "enzyme-to-json/serializer" + ], + "moduleNameMapper": { + "^.+\\.(css|scss)$": "identity-obj-proxy", + "\\.(jpg|jpeg|png)$": "/src/__mocks__/fileMock.js" + } }, "dependencies": { "animate.scss": "0.0.6", @@ -61,6 +74,9 @@ "babel-register": "^6.22.0", "brunch": "2.10.9", "clean-css-brunch": "^2.10.0", + "enzyme": "^3.3.0", + "enzyme-adapter-react-16": "^1.1.1", + "enzyme-to-json": "^3.3.1", "gzip-brunch": "^1.3.0", "html-pages-brunch": "^2.6.0", "jest": "^22.0.6", diff --git a/tests_setup.js b/tests_setup.js new file mode 100644 index 000000000..da3da5ba6 --- /dev/null +++ b/tests_setup.js @@ -0,0 +1,17 @@ +import Enzyme, { shallow, render, mount } from 'enzyme' +import Adapter from 'enzyme-adapter-react-16' +import React from 'react' + + +global.React = React + +// React 16 Enzyme adapter +Enzyme.configure({ adapter: new Adapter() }) + +// Make Enzyme functions available in all test files without importing +global.shallow = shallow +global.render = render +global.mount = mount + +// Add a helper to register snapshot +global.snapshot = component => expect(shallow(component)).toMatchSnapshot() From 583624729f012dc55fdec8bfd9e7952640809b73 Mon Sep 17 00:00:00 2001 From: Benjamin Piouffle Date: Tue, 20 Feb 2018 16:50:15 +1100 Subject: [PATCH 6/6] Bump version to 0.8.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f476f5143..74ea98021 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "captain-fact-frontend", - "version": "0.8.0", + "version": "0.8.2", "private": true, "scripts": { "start": "brunch watch --server",