From 1af4acbb3d8758966c4dea70137623f7a2b65c1b Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Mon, 11 Sep 2017 10:31:38 -0400 Subject: [PATCH] Add tests to flagged topics --- .../modals/admin-agree-flag.js.es6 | 24 ++-- .../modals/admin-delete-flag.js.es6 | 6 + .../admin/models/admin-user.js.es6 | 85 ++++++------ .../admin/models/flagged-post.js.es6 | 8 +- .../templates/components/flagged-post.hbs | 8 +- .../templates/components/flagged-posts.hbs | 1 - .../components/flagged-topic-users.hbs | 2 +- .../admin/templates/flags-topics-index.hbs | 4 +- .../admin/templates/flags-topics-show.hbs | 5 +- .../templates/modal/admin-agree-flag.hbs | 30 ++++- .../templates/modal/admin-delete-flag.hbs | 23 +++- .../discourse/routes/application.js.es6 | 3 +- .../javascripts/pretty-text/emoji.js.es6.erb | 2 + .../acceptance/admin-flags-test.js.es6 | 121 ++++++++++++++++++ .../acceptance/admin-flags-topics-test.js.es6 | 11 -- .../helpers/create-pretender.js.es6 | 13 +- .../javascripts/helpers/flag-pretender.js.es6 | 58 +++++++++ 17 files changed, 315 insertions(+), 89 deletions(-) create mode 100644 test/javascripts/acceptance/admin-flags-test.js.es6 delete mode 100644 test/javascripts/acceptance/admin-flags-topics-test.js.es6 create mode 100644 test/javascripts/helpers/flag-pretender.js.es6 diff --git a/app/assets/javascripts/admin/controllers/modals/admin-agree-flag.js.es6 b/app/assets/javascripts/admin/controllers/modals/admin-agree-flag.js.es6 index 43b14f4dbb1..8534d64b4fc 100644 --- a/app/assets/javascripts/admin/controllers/modals/admin-agree-flag.js.es6 +++ b/app/assets/javascripts/admin/controllers/modals/admin-agree-flag.js.es6 @@ -2,18 +2,20 @@ import ModalFunctionality from 'discourse/mixins/modal-functionality'; export default Ember.Controller.extend(ModalFunctionality, { removeAfter: null, - - _agreeFlag(action) { - let flaggedPost = this.get('model'); - return this.removeAfter(flaggedPost.agreeFlags(action)).then(() => { - this.send('closeModal'); - }); - }, + deleteSpammer: null, actions: { - agreeFlagHidePost() { return this._agreeFlag("hide"); }, - agreeFlagKeepPost() { return this._agreeFlag("keep"); }, - agreeFlagRestorePost() { return this._agreeFlag("restore"); } - } + agreeDeleteSpammer(user) { + return this.removeAfter(user.deleteAsSpammer()).then(() => { + this.send('closeModal'); + }); + }, + perform(action) { + let flaggedPost = this.get('model'); + return this.removeAfter(flaggedPost.agreeFlags(action)).then(() => { + this.send('closeModal'); + }); + }, + } }); diff --git a/app/assets/javascripts/admin/controllers/modals/admin-delete-flag.js.es6 b/app/assets/javascripts/admin/controllers/modals/admin-delete-flag.js.es6 index be9f74d0eff..f972465ae97 100644 --- a/app/assets/javascripts/admin/controllers/modals/admin-delete-flag.js.es6 +++ b/app/assets/javascripts/admin/controllers/modals/admin-delete-flag.js.es6 @@ -4,6 +4,12 @@ export default Ember.Controller.extend(ModalFunctionality, { removeAfter: null, actions: { + deleteSpammer(user) { + return this.removeAfter(user.deleteAsSpammer()).then(() => { + this.send('closeModal'); + }); + }, + deletePostDeferFlag() { let flaggedPost = this.get('model'); this.removeAfter(flaggedPost.deferFlags(true)).then(() => { diff --git a/app/assets/javascripts/admin/models/admin-user.js.es6 b/app/assets/javascripts/admin/models/admin-user.js.es6 index 662f0b046ca..18431757280 100644 --- a/app/assets/javascripts/admin/models/admin-user.js.es6 +++ b/app/assets/javascripts/admin/models/admin-user.js.es6 @@ -463,49 +463,56 @@ const AdminUser = Discourse.User.extend({ bootbox.dialog(message, buttons, { "classes": "delete-user-modal" }); }, - deleteAsSpammer(successCallback) { - const user = this; + deleteAsSpammer() { + return this.checkEmail().then(() => { - user.checkEmail().then(function() { - const data = { - "POSTS": user.get('post_count'), - "TOPICS": user.get('topic_count'), - email: user.get('email') || I18n.t("flagging.hidden_email_address"), - ip_address: user.get('ip_address') || I18n.t("flagging.ip_address_missing") - }; + let message = I18n.messageFormat('flagging.delete_confirm_MF', { + "POSTS": this.get('post_count'), + "TOPICS": this.get('topic_count'), + email: this.get('email') || I18n.t("flagging.hidden_email_address"), + ip_address: this.get('ip_address') || I18n.t("flagging.ip_address_missing") + }); - const message = I18n.messageFormat('flagging.delete_confirm_MF', data), - buttons = [{ - "label": I18n.t("composer.cancel"), - "class": "cancel-inline", - "link": true - }, { - "label": `${iconHTML('exclamation-triangle')} ` + I18n.t("flagging.yes_delete_spammer"), - "class": "btn btn-danger", - "callback": function() { - return ajax("/admin/users/" + user.get('id') + '.json', { - type: 'DELETE', - data: { - delete_posts: true, - block_email: true, - block_urls: true, - block_ip: true, - delete_as_spammer: true, - context: window.location.pathname + let userId = this.get('id'); + + return new Ember.RSVP.Promise((resolve, reject) => { + const buttons = [ + { + label: I18n.t("composer.cancel"), + class: "cancel-inline", + link: true + }, + { + label: `${iconHTML('exclamation-triangle')} ` + I18n.t("flagging.yes_delete_spammer"), + class: "btn btn-danger confirm-delete", + callback() { + return ajax(`/admin/users/${userId}.json`, { + type: 'DELETE', + data: { + delete_posts: true, + block_email: true, + block_urls: true, + block_ip: true, + delete_as_spammer: true, + context: window.location.pathname + } + }).then(result => { + if (result.deleted) { + resolve(); + } else { + throw 'failed to delete'; + } + }).catch(() => { + bootbox.alert(I18n.t("admin.user.delete_failed")); + reject(); + }); } - }).then(function(result) { - if (result.deleted) { - if (successCallback) successCallback(); - } else { - bootbox.alert(I18n.t("admin.user.delete_failed")); - } - }).catch(function() { - bootbox.alert(I18n.t("admin.user.delete_failed")); - }); - } - }]; + } + ]; + + bootbox.dialog(message, buttons, {classes: "flagging-delete-spammer"}); + }); - bootbox.dialog(message, buttons, {"classes": "flagging-delete-spammer"}); }); }, diff --git a/app/assets/javascripts/admin/models/flagged-post.js.es6 b/app/assets/javascripts/admin/models/flagged-post.js.es6 index 4f1cc61d106..b2198e75ca4 100644 --- a/app/assets/javascripts/admin/models/flagged-post.js.es6 +++ b/app/assets/javascripts/admin/models/flagged-post.js.es6 @@ -92,7 +92,7 @@ const FlaggedPost = Post.extend({ @computed('post_actions.@each.name_key') flaggedForSpam() { - return !_.every(this.get('post_actions'), function(action) { return action.name_key !== 'spam'; }); + return this.get('post_actions').every(action => action.name_key === 'spam'); }, @computed('post_actions.@each.targets_topic') @@ -105,9 +105,11 @@ const FlaggedPost = Post.extend({ return _.any(this.get('post_actions'), function(action) { return !action.targets_topic; }); }, - @computed('flaggedForSpan') + @computed('flaggedForSpam') canDeleteAsSpammer(flaggedForSpam) { - return Discourse.User.currentProp('staff') && flaggedForSpam && this.get('user.can_delete_all_posts') && this.get('user.can_be_deleted'); + return flaggedForSpam && + this.get('user.can_delete_all_posts') && + this.get('user.can_be_deleted'); }, deletePost() { diff --git a/app/assets/javascripts/admin/templates/components/flagged-post.hbs b/app/assets/javascripts/admin/templates/components/flagged-post.hbs index dd420a24f92..69a9a302c82 100644 --- a/app/assets/javascripts/admin/templates/components/flagged-post.hbs +++ b/app/assets/javascripts/admin/templates/components/flagged-post.hbs @@ -47,7 +47,7 @@ {{#each flaggedPost.flaggers as |flagger|}} - {{#link-to 'adminUser' flagger.user}} + {{#link-to 'adminUser' flagger.user class='flagger'}} {{avatar flagger.user imageSize="medium"}} {{/link-to}} @@ -135,6 +135,7 @@ {{d-button title="admin.flags.agree_title" + class="agree-flag" label="admin.flags.agree" icon="thumbs-o-up" action="showAgreeFlagModal" @@ -143,25 +144,28 @@ {{#if flaggedPost.postHidden}} {{d-button title="admin.flags.disagree_flag_unhide_post_title" + class="disagree-flag" action="disagree" icon="thumbs-o-down" label="admin.flags.disagree_flag_unhide_post"}} {{else}} {{d-button title="admin.flags.disagree_flag_title" + class="disagree-flag" action="disagree" icon="thumbs-o-down" label="admin.flags.disagree_flag"}} {{/if}} {{d-button + class="defer-flag" title="admin.flags.defer_flag_title" action="defer" icon="external-link" label="admin.flags.defer_flag"}} {{d-button - class="btn-danger" + class="btn-danger delete-flag" title="admin.flags.delete_title" action="showDeleteFlagModal" icon="trash-o" diff --git a/app/assets/javascripts/admin/templates/components/flagged-posts.hbs b/app/assets/javascripts/admin/templates/components/flagged-posts.hbs index 583b35c11a7..ff1073db43d 100644 --- a/app/assets/javascripts/admin/templates/components/flagged-posts.hbs +++ b/app/assets/javascripts/admin/templates/components/flagged-posts.hbs @@ -17,7 +17,6 @@ removePost=(action "removePost" flaggedPost) hideTitle=topic}} {{/each}} - {{/load-more}} diff --git a/app/assets/javascripts/admin/templates/components/flagged-topic-users.hbs b/app/assets/javascripts/admin/templates/components/flagged-topic-users.hbs index dfc4b3da425..ac6935672c9 100644 --- a/app/assets/javascripts/admin/templates/components/flagged-topic-users.hbs +++ b/app/assets/javascripts/admin/templates/components/flagged-topic-users.hbs @@ -1,5 +1,5 @@ {{#each users as |u|}} - {{#link-to 'adminUser' u}} + {{#link-to 'adminUser' u class="flagged-topic-user"}} {{avatar u imageSize="small"}} {{/link-to}} {{/each}} diff --git a/app/assets/javascripts/admin/templates/flags-topics-index.hbs b/app/assets/javascripts/admin/templates/flags-topics-index.hbs index 110df355f62..61ef340129d 100644 --- a/app/assets/javascripts/admin/templates/flags-topics-index.hbs +++ b/app/assets/javascripts/admin/templates/flags-topics-index.hbs @@ -22,7 +22,7 @@ {{flag-counts details=fc}} {{/each}} - + {{flagged-topic-users users=ft.users tagName=""}} @@ -32,7 +32,7 @@ {{#link-to "adminFlags.topics.show" ft.id - class="btn d-button no-text btn-small btn-primary" + class="btn d-button no-text btn-small btn-primary show-details" title=(i18n "admin.flags.show_details")}} {{d-icon "search"}} {{/link-to}} diff --git a/app/assets/javascripts/admin/templates/flags-topics-show.hbs b/app/assets/javascripts/admin/templates/flags-topics-show.hbs index fae256e8ab2..225b21177d4 100644 --- a/app/assets/javascripts/admin/templates/flags-topics-show.hbs +++ b/app/assets/javascripts/admin/templates/flags-topics-show.hbs @@ -11,5 +11,8 @@ {{plugin-outlet name="flagged-topic-details-header" args=(hash topic=topic)}}
- {{flagged-posts flaggedPosts=flaggedPosts query="active" topic=topic}} + {{flagged-posts + flaggedPosts=flaggedPosts + filter="active" + topic=topic}}
diff --git a/app/assets/javascripts/admin/templates/modal/admin-agree-flag.hbs b/app/assets/javascripts/admin/templates/modal/admin-agree-flag.hbs index 63ce16601bd..a69ae42877e 100644 --- a/app/assets/javascripts/admin/templates/modal/admin-agree-flag.hbs +++ b/app/assets/javascripts/admin/templates/modal/admin-agree-flag.hbs @@ -1,13 +1,35 @@ {{#d-modal-body title="admin.flags.agree_flag_modal_title"}} {{#if model.user_deleted}} - + {{d-button + title="admin.flags.agree_flag_restore_post_title" + class="confirm-agree-restore" + action=(action "perform" "restore") + icon="eye" + label="admin.flags.agree_flag_restore_post"}} {{else}} {{#unless model.postHidden}} - + {{d-button + title="admin.flags.agree_flag_hide_post_title" + action=(action "perform" "hide") + class="confirm-agree-hide" + icon="eye-slash" + label="admin.flags.agree_flag_hide_post"}} {{/unless}} {{/if}} - + + {{d-button + title="admin.flags.agree_flag_title" + action=(action "perform" "keep") + class="confirm-agree-keep" + icon="thumbs-o-up" + label="admin.flags.agree_flag"}} + {{#if model.canDeleteAsSpammer}} - + {{d-button + title="admin.flags.delete_spammer_title" + action=(action "agreeDeleteSpammer" model.user) + class="btn-danger delete-spammer" + icon="exclamation-triangle" + label="admin.flags.delete_spammer"}} {{/if}} {{/d-modal-body}} diff --git a/app/assets/javascripts/admin/templates/modal/admin-delete-flag.hbs b/app/assets/javascripts/admin/templates/modal/admin-delete-flag.hbs index 89cf7452a4c..d27c10d1127 100644 --- a/app/assets/javascripts/admin/templates/modal/admin-delete-flag.hbs +++ b/app/assets/javascripts/admin/templates/modal/admin-delete-flag.hbs @@ -1,7 +1,24 @@ {{#d-modal-body title="admin.flags.delete_flag_modal_title"}} - - + {{d-button + class="delete-defer" + title="admin.flags.delete_post_defer_flag_title" + action="deletePostDeferFlag" + icon="external-link" + label="admin.flags.delete_post_defer_flag"}} + + {{d-button + class="delete-agree" + title="admin.flags.delete_post_agree_flag_title" + action="deletePostAgreeFlag" + icon="thumbs-o-up" + label="admin.flags.delete_post_agree_flag"}} + {{#if model.canDeleteAsSpammer}} - + {{d-button + class="btn-danger delete-spammer" + title="admin.flags.delete_spammer_title" + action=(action "deleteSpammer" model.user) + icon="exclamation-triangle" + label="admin.flags.delete_spammer"}} {{/if}} {{/d-modal-body}} diff --git a/app/assets/javascripts/discourse/routes/application.js.es6 b/app/assets/javascripts/discourse/routes/application.js.es6 index 93598fbb9bd..c53dd857129 100644 --- a/app/assets/javascripts/discourse/routes/application.js.es6 +++ b/app/assets/javascripts/discourse/routes/application.js.es6 @@ -139,8 +139,7 @@ const ApplicationRoute = Discourse.Route.extend(OpenComposer, { }, deleteSpammer(user) { - this.send('closeModal'); - user.deleteAsSpammer(function() { window.location.reload(); }); + user.deleteAsSpammer.then(() => window.location.reload()); }, checkEmail(user) { diff --git a/app/assets/javascripts/pretty-text/emoji.js.es6.erb b/app/assets/javascripts/pretty-text/emoji.js.es6.erb index 136c2904261..fc7f79c94b6 100644 --- a/app/assets/javascripts/pretty-text/emoji.js.es6.erb +++ b/app/assets/javascripts/pretty-text/emoji.js.es6.erb @@ -26,6 +26,8 @@ Object.keys(aliases).forEach(name => { }); export function performEmojiUnescape(string, opts) { + if (!string) { return; } + // this can be further improved by supporting matches of emoticons that don't begin with a colon if (string.indexOf(":") >= 0) { return string.replace(/\B:[^\s:]+(?::t\d)?:?\B/g, m => { diff --git a/test/javascripts/acceptance/admin-flags-test.js.es6 b/test/javascripts/acceptance/admin-flags-test.js.es6 new file mode 100644 index 00000000000..1da3ce45f26 --- /dev/null +++ b/test/javascripts/acceptance/admin-flags-test.js.es6 @@ -0,0 +1,121 @@ +import { acceptance } from "helpers/qunit-helpers"; +acceptance("Admin - Flagging", { loggedIn: true }); + +QUnit.test("flagged posts", assert => { + visit("/admin/flags/active"); + andThen(() => { + assert.equal(find('.admin-flags .flagged-post').length, 1); + assert.equal(find('.flagged-post .flaggers .flagger').length, 1, 'shows who flagged it'); + }); +}); + +QUnit.test("flagged posts - agree", assert => { + visit("/admin/flags/active"); + click('.agree-flag'); + andThen(() => { + assert.equal(find('.agree-flag-modal:visible').length, 1); + }); + click('.confirm-agree-keep'); + andThen(() => { + assert.equal(find('.agree-flag-modal:visible').length, 0, 'modal is closed'); + assert.equal(find('.admin-flags .flagged-post').length, 0, 'post was removed'); + }); +}); + +QUnit.test("flagged posts - agree + hide", assert => { + visit("/admin/flags/active"); + click('.agree-flag'); + andThen(() => { + assert.equal(find('.agree-flag-modal:visible').length, 1); + }); + click('.confirm-agree-hide'); + andThen(() => { + assert.equal(find('.agree-flag-modal:visible').length, 0, 'modal is closed'); + assert.equal(find('.admin-flags .flagged-post').length, 0, 'post was removed'); + }); +}); + +QUnit.test("flagged posts - agree + deleteSpammer", assert => { + visit("/admin/flags/active"); + click('.agree-flag'); + andThen(() => { + assert.equal(find('.agree-flag-modal:visible').length, 1); + }); + click('.delete-spammer'); + click('.confirm-delete'); + andThen(() => { + assert.equal(find('.agree-flag-modal:visible').length, 0, 'modal is closed'); + assert.equal(find('.admin-flags .flagged-post').length, 0, 'post was removed'); + }); +}); + +QUnit.test("flagged posts - disagree", assert => { + visit("/admin/flags/active"); + click('.disagree-flag'); + andThen(() => { + assert.equal(find('.admin-flags .flagged-post').length, 0); + }); +}); + +QUnit.test("flagged posts - defer", assert => { + visit("/admin/flags/active"); + click('.defer-flag'); + andThen(() => { + assert.equal(find('.admin-flags .flagged-post').length, 0); + }); +}); + +QUnit.test("flagged posts - delete + defer", assert => { + visit("/admin/flags/active"); + click('.delete-flag'); + andThen(() => { + assert.equal(find('.delete-flag-modal:visible').length, 1); + }); + click('.delete-defer'); + andThen(() => { + assert.equal(find('.delete-flag-modal:visible').length, 0); + assert.equal(find('.admin-flags .flagged-post').length, 0); + }); +}); + +QUnit.test("flagged posts - delete + agree", assert => { + visit("/admin/flags/active"); + click('.delete-flag'); + andThen(() => { + assert.equal(find('.delete-flag-modal:visible').length, 1); + }); + click('.delete-agree'); + andThen(() => { + assert.equal(find('.delete-flag-modal:visible').length, 0); + assert.equal(find('.admin-flags .flagged-post').length, 0); + }); +}); + +QUnit.test("flagged posts - delete + deleteSpammer", assert => { + visit("/admin/flags/active"); + click('.delete-flag'); + andThen(() => { + assert.equal(find('.delete-flag-modal:visible').length, 1); + }); + click('.delete-spammer'); + click('.confirm-delete'); + andThen(() => { + assert.equal(find('.delete-flag-modal:visible').length, 0); + assert.equal(find('.admin-flags .flagged-post').length, 0); + }); +}); + + +QUnit.test("topics with flags", assert => { + visit("/admin/flags/topics"); + andThen(() => { + assert.equal(find('.flagged-topics .flagged-topic').length, 1); + assert.equal(find('.flagged-topic .flagged-topic-user').length, 2); + assert.equal(find('.flagged-topic .flag-counts').length, 3); + }); + + click('.flagged-topic .show-details'); + andThen(() => { + assert.equal(currentURL(), '/admin/flags/topics/280'); + }); +}); diff --git a/test/javascripts/acceptance/admin-flags-topics-test.js.es6 b/test/javascripts/acceptance/admin-flags-topics-test.js.es6 deleted file mode 100644 index 23e6f56ddc2..00000000000 --- a/test/javascripts/acceptance/admin-flags-topics-test.js.es6 +++ /dev/null @@ -1,11 +0,0 @@ -import { acceptance } from "helpers/qunit-helpers"; -acceptance("Admin - Flagged Topics", { loggedIn: true }); - -QUnit.test("topics with flags", assert => { - visit("/admin/flags/topics"); - andThen(() => { - assert.ok(exists('.watched-words-list')); - assert.ok(!exists('.watched-words-list .watched-word'), "Don't show bad words by default."); - }); -}); - diff --git a/test/javascripts/helpers/create-pretender.js.es6 b/test/javascripts/helpers/create-pretender.js.es6 index a803bccfe43..f7e4d8df2be 100644 --- a/test/javascripts/helpers/create-pretender.js.es6 +++ b/test/javascripts/helpers/create-pretender.js.es6 @@ -1,5 +1,6 @@ import storePretender from 'helpers/store-pretender'; import fixturePretender from 'helpers/fixture-pretender'; +import flagPretender from 'helpers/flag-pretender'; export function parsePostData(query) { const result = {}; @@ -41,6 +42,7 @@ export default function() { const server = new Pretender(function() { storePretender.call(this, helpers); + flagPretender.call(this, helpers); const fixturesByUrl = fixturePretender.call(this, helpers); this.get('/admin/plugins', () => response({ plugins: [] })); @@ -66,7 +68,7 @@ export default function() { }] }); }); - this.get(`/u/eviltrout/emails.json`, () => { + this.get(`/u/:username/emails.json`, () => { return response({ email: 'eviltrout@example.com' }); }); @@ -323,14 +325,6 @@ export default function() { ]); }); - this.get('/admin/flagged_topics', () => { - return response(200, { - "flagged_topics": [ - { id: 1 } - ] - }); - }); - this.get('/admin/customize/site_texts', request => { if (request.queryParams.overridden) { @@ -353,6 +347,7 @@ export default function() { this.get('/tag_groups', () => response(200, {tag_groups: []})); this.post('/admin/users/:user_id/generate_api_key', success); this.delete('/admin/users/:user_id/revoke_api_key', success); + this.delete('/admin/users/:user_id.json', () => response(200, { deleted: true })); this.post('/admin/badges', success); this.delete('/admin/badges/:id', success); diff --git a/test/javascripts/helpers/flag-pretender.js.es6 b/test/javascripts/helpers/flag-pretender.js.es6 new file mode 100644 index 00000000000..5ce060aacf7 --- /dev/null +++ b/test/javascripts/helpers/flag-pretender.js.es6 @@ -0,0 +1,58 @@ +export default function(helpers) { + const { response, success } = helpers; + + const eviltrout = { + id: 1, + username: "eviltrout", + avatar_template:"/images/avatar.png", + }; + const sam = { + id: 2, + username: "sam", + avatar_template:"/images/avatar.png", + can_delete_all_posts: true, + can_be_deleted: true, + post_count: 1, + topic_count: 0 + }; + + this.get('/admin/flagged_topics', () => { + return response(200, { + "flagged_topics": [ + { + id: 280, + user_ids: [eviltrout.id, sam.id], + flag_counts: [ + { flag_type_id: 1, count: 3 }, + { flag_type_id: 2, count: 2 }, + { flag_type_id: 3, count: 1 }, + ] + } + ], + "users": [ eviltrout, sam ], + "__rest_serializer":"1" + }); + }); + + this.get('/admin/flags/active.json', () => { + return response(200, { + posts: [ + { + id: 1, + user_id: sam.id, + post_actions: [{ + user_id: eviltrout.id, + post_action_type_id: 8, + name_key: 'spam' + }] + } + ], + users: [eviltrout, sam], + topics: [], + }); + }); + + this.post('/admin/flags/agree/1', success); + this.post('/admin/flags/defer/1', success); + this.post('/admin/flags/disagree/1', success); +}