diff --git a/app/assets/javascripts/discourse/templates/user/user.hbs b/app/assets/javascripts/discourse/templates/user/user.hbs index 2aaa4a90c..973faae83 100644 --- a/app/assets/javascripts/discourse/templates/user/user.hbs +++ b/app/assets/javascripts/discourse/templates/user/user.hbs @@ -67,7 +67,7 @@
- +
+<%=submit_tag( @user.has_password? ? t('password_reset.update') : t('password_reset.save'), class: 'btn')%>
@@ -48,5 +49,11 @@ diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 3f48bb93a..de3b8afc7 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -375,7 +375,7 @@ en: dismiss_notifications: "Mark all as Read" dismiss_notifications_tooltip: "Mark all unread notifications as read" disable_jump_reply: "Don't jump to my post after I reply" - dynamic_favicon: "Show incoming message notifications on favicon (experimental)" + dynamic_favicon: "Show new / updated topic count on browser icon" edit_history_public: "Let other users view my post revisions" external_links_in_new_tab: "Open all external links in a new tab" enable_quoting: "Enable quote reply for highlighted text" diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index b599e0606..0db4cbc5a 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -823,7 +823,7 @@ en: traditional_markdown_linebreaks: "Use traditional linebreaks in Markdown, which require two trailing spaces for a linebreak." post_undo_action_window_mins: "Number of minutes users are allowed to undo recent actions on a post (like, flag, etc)." - must_approve_users: "Staff must approve all new user accounts before they are allowed to access the site." + must_approve_users: "Staff must approve all new user accounts before they are allowed to access the site. WARNING: enabling this for a live site will revoke access for existing non-staff users!" ga_tracking_code: "Google analytics (ga.js) tracking code code, eg: UA-12345678-9; see http://google.com/analytics" ga_domain_name: "Google analytics (ga.js) domain name, eg: mysite.com; see http://google.com/analytics" ga_universal_tracking_code: "Google Universal Analytics (analytics.js) tracking code code, eg: UA-12345678-9; see http://google.com/analytics" @@ -1443,7 +1443,7 @@ en: %{flag_reason} - Multiple community members flagged this post before it was hidden, so please consider how you might revise your post to reflect their feedback. **You can edit your post after %{edit_delay} minutes, and it will be automatically unhidden.** This will increase your trust level. + Multiple community members flagged this post before it was hidden, so please consider how you might revise your post to reflect their feedback. **You can edit your post after %{edit_delay} minutes, and it will be automatically unhidden.** However, if the post is hidden by the community a second time, it will remain hidden until handled by staff – and there may be further action, including the possible suspension of your account. diff --git a/lib/new_post_manager.rb b/lib/new_post_manager.rb index 5dcc8bdbc..7e440f847 100644 --- a/lib/new_post_manager.rb +++ b/lib/new_post_manager.rb @@ -50,6 +50,9 @@ class NewPostManager def perform + # We never queue private messages + return perform_create_post if @args[:archetype] == Archetype.private_message + # Perform handlers until one returns a result handled = NewPostManager.handlers.any? do |handler| result = handler.call(self) diff --git a/lib/plugin/instance.rb b/lib/plugin/instance.rb index 8c0370c2f..42b2e8bf9 100644 --- a/lib/plugin/instance.rb +++ b/lib/plugin/instance.rb @@ -217,9 +217,6 @@ class Plugin::Instance DiscoursePluginRegistry.register_glob(root_path, 'hbs') end - # Automatically include all rake tasks - Rake.add_rakelib "#{File.dirname(path)}/lib/tasks" - self.instance_eval File.read(path), path if auto_assets = generate_automatic_assets! assets.concat auto_assets.map{|a| [a]} @@ -227,10 +224,18 @@ class Plugin::Instance register_assets! unless assets.blank? - # TODO possibly amend this to a rails engine + # TODO: possibly amend this to a rails engine + + # Automatically include assets Rails.configuration.assets.paths << auto_generated_path Rails.configuration.assets.paths << File.dirname(path) + "/assets" + # Automatically include rake tasks + Rake.add_rakelib(File.dirname(path) + "/lib/tasks") + + # Automatically include migrations + Rails.configuration.paths["db/migrate"] << File.dirname(path) + "/db/migrate" + public_data = File.dirname(path) + "/public" if Dir.exists?(public_data) target = Rails.root.to_s + "/public/plugins/" diff --git a/plugins/poll/assets/javascripts/components/poll-results-number.js.es6 b/plugins/poll/assets/javascripts/components/poll-results-number.js.es6 index 4e7c6b35f..da48d4abb 100644 --- a/plugins/poll/assets/javascripts/components/poll-results-number.js.es6 +++ b/plugins/poll/assets/javascripts/components/poll-results-number.js.es6 @@ -12,9 +12,9 @@ export default Em.Component.extend({ }.property("poll.options.@each.{html,votes}"), average: function() { - const total_votes = this.get("poll.total_votes"); - return total_votes == 0 ? 0 : round(this.get("totalScore") / total_votes, -2); - }.property("totalScore", "poll.total_votes"), + const voters = this.get("poll.voters"); + return voters === 0 ? 0 : round(this.get("totalScore") / voters, -2); + }.property("totalScore", "poll.voters"), averageRating: function() { return I18n.t("poll.average_rating", { average: this.get("average") }); diff --git a/plugins/poll/assets/javascripts/components/poll-results-standard.js.es6 b/plugins/poll/assets/javascripts/components/poll-results-standard.js.es6 index 21f213d83..64abdf668 100644 --- a/plugins/poll/assets/javascripts/components/poll-results-standard.js.es6 +++ b/plugins/poll/assets/javascripts/components/poll-results-standard.js.es6 @@ -3,11 +3,11 @@ export default Em.Component.extend({ classNames: ["results"], options: function() { - const totalVotes = this.get("poll.total_votes"), + const voters = this.get("poll.voters"), backgroundColor = this.get("poll.background"); this.get("poll.options").forEach(option => { - const percentage = totalVotes == 0 ? 0 : Math.floor(100 * option.get("votes") / totalVotes), + const percentage = voters === 0 ? 0 : Math.floor(100 * option.get("votes") / voters), styles = ["width: " + percentage + "%"]; if (backgroundColor) { styles.push("background: " + backgroundColor); } @@ -20,6 +20,6 @@ export default Em.Component.extend({ }); return this.get("poll.options"); - }.property("poll.total_votes", "poll.options.[]") + }.property("poll.voters", "poll.options.[]") }); diff --git a/plugins/poll/assets/javascripts/controllers/poll.js.es6 b/plugins/poll/assets/javascripts/controllers/poll.js.es6 index cfbd9b862..ef3ebce95 100644 --- a/plugins/poll/assets/javascripts/controllers/poll.js.es6 +++ b/plugins/poll/assets/javascripts/controllers/poll.js.es6 @@ -4,16 +4,13 @@ export default Em.Controller.extend({ isRandom : Em.computed.equal("poll.order", "random"), isClosed: Em.computed.equal("poll.status", "closed"), - // immediately shows the results when the user has already voted - showResults: Em.computed.gt("vote.length", 0), - // shows the results when // - poll is closed // - topic is archived/closed // - user wants to see the results showingResults: Em.computed.or("isClosed", "post.topic.closed", "post.topic.archived", "showResults"), - showResultsDisabled: Em.computed.equal("poll.total_votes", 0), + showResultsDisabled: Em.computed.equal("poll.voters", 0), hideResultsDisabled: Em.computed.alias("isClosed"), poll: function() { @@ -37,10 +34,6 @@ export default Em.Controller.extend({ return _.map(this.get("poll.options").filterBy("selected"), o => o.get("id")); }.property("poll.options.@each.selected"), - totalVotesText: function() { - return I18n.t("poll.total_votes", { count: this.get("poll.total_votes") }); - }.property("poll.total_votes"), - min: function() { let min = parseInt(this.get("poll.min"), 10); if (isNaN(min) || min < 1) { min = 1; } @@ -54,6 +47,20 @@ export default Em.Controller.extend({ return max; }.property("poll.max", "poll.options.length"), + votersText: function() { + return I18n.t("poll.voters", { count: this.get("poll.voters") }); + }.property("poll.voters"), + + totalVotes: function() { + return _.reduce(this.get("poll.options"), function(total, o) { + return total + parseInt(o.get("votes"), 10); + }, 0); + }.property("poll.options.@each.votes"), + + totalVotesText: function() { + return I18n.t("poll.total_votes", { count: this.get("totalVotes") }); + }.property("totalVotes"), + multipleHelpText: function() { const options = this.get("poll.options.length"), min = this.get("min"), diff --git a/plugins/poll/assets/javascripts/discourse/templates/components/poll-results-standard.hbs b/plugins/poll/assets/javascripts/discourse/templates/components/poll-results-standard.hbs index ccd3b1beb..b17c1361e 100644 --- a/plugins/poll/assets/javascripts/discourse/templates/components/poll-results-standard.hbs +++ b/plugins/poll/assets/javascripts/discourse/templates/components/poll-results-standard.hbs @@ -1,13 +1,11 @@ - - {{#each option in options}} -+ {{poll.voters}} + {{votersText}} +
+ {{#if isMultiple}} + {{#if showingResults}} ++ {{totalVotes}} + {{totalVotesText}} +
+ {{else}} +{{{multipleHelpText}}}
+ {{/if}} {{/if}} - {{else}} -{{totalVotesText}}
- -{{#if isMultiple}} -{{multipleHelpText}}
- {{d-button class="cast-votes" title="poll.cast-votes.title" label="poll.cast-votes.label" disabled=castVotesDisabled action="castVotes"}} -{{/if}} - -{{#if showingResults}} - {{d-button class="toggle-results" title="poll.hide-results.title" label="poll.hide-results.label" icon="eye-slash" disabled=hideResultsDisabled action="toggleResults"}} -{{else}} - {{d-button class="toggle-results" title="poll.show-results.title" label="poll.show-results.label" icon="eye" disabled=showResultsDisabled action="toggleResults"}} -{{/if}} - -{{#if canToggleStatus}} - {{#if isClosed}} - {{d-button class="toggle-status" title="poll.open.title" label="poll.open.label" icon="unlock-alt" action="toggleStatus"}} - {{else}} - {{d-button class="toggle-status btn-danger" title="poll.close.title" label="poll.close.label" icon="lock" action="toggleStatus"}} + diff --git a/plugins/poll/assets/javascripts/poll_dialect.js b/plugins/poll/assets/javascripts/poll_dialect.js index e752762fa..bab447477 100644 --- a/plugins/poll/assets/javascripts/poll_dialect.js +++ b/plugins/poll/assets/javascripts/poll_dialect.js @@ -97,13 +97,25 @@ contents[0][o].splice(1, 0, attr); } - // that's our poll! - var result = ["div", attributes].concat(contents); + // // add some information when type is "multiple" + // if (attributes[DATA_PREFIX + "type"] === "multiple") { - // add a small paragraph displaying the total number of votes - result.push(["p", I18n.t("poll.total_votes", { count: 0 })]); - // add some information when type is "multiple" + // } + + var result = ["div", attributes], + poll = ["div"]; + + // 1 - POLL INFO + var info = ["div", { "class": "poll-info" }]; + + // # of voters + info.push(["p", + ["span", { "class": "info-number" }, "0"], + ["span", { "class": "info-text"}, I18n.t("poll.voters", { count: 0 })] + ]); + + // multiple help text if (attributes[DATA_PREFIX + "type"] === "multiple") { var optionCount = contents[0].length - 1; @@ -130,22 +142,40 @@ } } - if (help) { result.push(["p", help]); } + if (help) { info.push(["p", help]); } + } - // add "cast-votes" button - result.push(["a", { "class": "button cast-votes", "title": I18n.t("poll.cast-votes.title") }, I18n.t("poll.cast-votes.label")]); + poll.push(info); + + // 2 - POLL CONTAINER + var container = ["div", { "class": "poll-container" }].concat(contents); + poll.push(container); + + // 3 - BUTTONS + var buttons = ["div", { "class": "poll-buttons" }]; + + // add "cast-votes" button + if (attributes[DATA_PREFIX + "type"] === "multiple") { + buttons.push(["a", { "class": "button cast-votes", "title": I18n.t("poll.cast-votes.title") }, I18n.t("poll.cast-votes.label")]); } // add "toggle-results" button - result.push(["a", { "class": "button toggle-results", "title": I18n.t("poll.show-results.title") }, I18n.t("poll.show-results.label")]); + buttons.push(["a", { "class": "button toggle-results", "title": I18n.t("poll.show-results.title") }, I18n.t("poll.show-results.label")]); + + // 4 - MIX IT ALL UP + result.push(poll); + result.push(buttons) return result; } }); Discourse.Markdown.whiteListTag("div", "class", "poll"); + Discourse.Markdown.whiteListTag("div", "class", /^poll-(info|container|buttons)/); Discourse.Markdown.whiteListTag("div", "data-*"); + Discourse.Markdown.whiteListTag("span", "class", /^info-(number|text)/); + Discourse.Markdown.whiteListTag("a", "class", /^button (cast-votes|toggle-results)/); Discourse.Markdown.whiteListTag("li", "data-*"); diff --git a/plugins/poll/assets/stylesheets/poll.scss b/plugins/poll/assets/stylesheets/poll.scss index ad35ea9a9..b61b1a600 100644 --- a/plugins/poll/assets/stylesheets/poll.scss +++ b/plugins/poll/assets/stylesheets/poll.scss @@ -1,11 +1,22 @@ +$border-color: rgb(219,219,219); +$text-color: #9E9E9E; + +$option-foreground: $primary; +$option-background: dark-light-diff($primary, $secondary, 90%, -65%); +$option-shadow: dark-light-diff($option-background, $primary, 10%, -10%); + div.poll { + display: table; + border: 1px solid $border-color; + width: 500px; + ul, ol { margin: 0; padding: 0; list-style: none; display: inline-block; - max-width: 90%; + width: 100%; } li, .option { @@ -15,31 +26,29 @@ div.poll { } li[data-poll-option-id] { - color: $secondary; - background: $primary; + position: relative; + color: $option-foreground; + background: $option-background; + box-shadow: 0 6px $option-shadow; padding: 0 .8em; margin-bottom: .7em; - border-radius: .25rem; - box-shadow: inset 0 -.2em 0 0 rgba(0,0,0,.2), - inset 0 0 0 100px rgba(0,0,0,0), - 0 .2em 0 0 rgba(0,0,0,.2); + border-radius: 4px; &:hover { - box-shadow: inset 0 -.2em 0 0 rgba(0,0,0,.25), - inset 0 0 0 100px rgba(0,0,0,.1), - 0 .2em 0 0 rgba(0,0,0,.2); + top: 2px; + box-shadow: 0 4px $option-shadow; } &:active { - -webkit-transform: translate(0,2px); - transform: translate(0,2px); - box-shadow: inset 0 -.1em 0 0 rgba(0,0,0,.25), - inset 0 0 0 100px rgba(0,0,0,.1), - 0 .1em 0 0 rgba(0,0,0,.2); + top: 6px; + box-shadow: 0 0 $option-shadow; } &[data-poll-selected="selected"] { - background: green !important; + background: $success !important; + box-shadow: 0 6px darken($success, 10%); + &:hover { box-shadow: 0 4px darken($success, 10%); } + &:active { box-shadow: 0 0 darken($success, 10%); } } } @@ -58,11 +67,45 @@ div.poll { } } + .poll-info { + color: $text-color; + width: 150px; + display: table-cell; + text-align: center; + vertical-align: middle; + border-right: 1px solid $border-color; + + p { + margin: 40px 20px; + } + + .info-number { + font-size: 3.5em; + } + + .info-text { + display: block; + font-size: 1.7em; + } + } + .poll-container { - margin: 0; + display: table-cell; + vertical-align: middle; + padding: 10px; + width: 330px; + span { - font-size: 1.125em; - line-height: 2 + font-size: 2em; + } + } + + .poll-buttons { + border-top: 1px solid $border-color; + padding: 10px; + + .toggle-status { + float: right; } } @@ -80,16 +123,16 @@ div.poll { font-size: 1.7em; text-align: right; vertical-align: middle; - color: #9E9E9E; + color: $text-color; } .bar-back { - background: rgb(219,219,219); + background: $border-color; } .bar { height: 10px; - background: $primary; + background: $option-foreground; } } @@ -98,7 +141,7 @@ div.poll { li { display: inline-block; - margin-right: .7em; + margin: 0 12px 15px 5px; } } diff --git a/plugins/poll/config/locales/client.en.yml b/plugins/poll/config/locales/client.en.yml index 24b5dc2f1..0096484b7 100644 --- a/plugins/poll/config/locales/client.en.yml +++ b/plugins/poll/config/locales/client.en.yml @@ -8,19 +8,23 @@ en: js: poll: + voters: + zero: "voters" + one: "voter" + other: "voters" total_votes: - zero: "No votes yet. Want to be the first?" - one: "There's only 1 vote." - other: "There are %{count} total votes." + zero: "total votes" + one: "total vote" + other: "total votes" average_rating: "Average rating: %{average}." multiple: help: - at_least_min_options: "You may choose at least %{count} options." - up_to_max_options: "You may choose up to %{count} options." - x_options: "You may choose %{count} options." - between_min_and_max_options: "You may choose between %{min} and %{max} options." + at_least_min_options: "You may choose at least %{count} options." + up_to_max_options: "You may choose up to %{count} options." + x_options: "You may choose %{count} options." + between_min_and_max_options: "You may choose between %{min} and %{max} options." cast-votes: title: "Cast your votes" diff --git a/plugins/poll/config/locales/client.es.yml b/plugins/poll/config/locales/client.es.yml index a64fc9ffd..d51dc84f1 100644 --- a/plugins/poll/config/locales/client.es.yml +++ b/plugins/poll/config/locales/client.es.yml @@ -8,7 +8,7 @@ es: js: poll: - total_votes: + voters: zero: "Sin votos todavía. ¿Quieres ser el primero?" one: "Sólo hay 1 voto." other: "Hay %{count} votos en total." diff --git a/plugins/poll/config/locales/client.fr.yml b/plugins/poll/config/locales/client.fr.yml index ad8450688..5e72189eb 100644 --- a/plugins/poll/config/locales/client.fr.yml +++ b/plugins/poll/config/locales/client.fr.yml @@ -8,7 +8,7 @@ fr: js: poll: - total_votes: + voters: zero: "Pas encore de votes. Soyez le premier !" one: "Il n'y a qu'un vote." other: "Il y a au total %{count} votes." diff --git a/plugins/poll/db/migrate/20150501152228_rename_total_votes_to_voters.rb b/plugins/poll/db/migrate/20150501152228_rename_total_votes_to_voters.rb new file mode 100644 index 000000000..902c84ded --- /dev/null +++ b/plugins/poll/db/migrate/20150501152228_rename_total_votes_to_voters.rb @@ -0,0 +1,29 @@ +class RenameTotalVotesToVoters < ActiveRecord::Migration + + def up + PostCustomField.where(name: "polls").find_each do |pcf| + polls = ::JSON.parse(pcf.value) + polls.each_value do |poll| + next if poll.has_key?("voters") + poll["voters"] = poll["total_votes"] + poll.delete("total_votes") + end + pcf.value = polls.to_json + pcf.save + end + end + + def down + PostCustomField.where(name: "polls").find_each do |pcf| + polls = ::JSON.parse(pcf.value) + polls.each_value do |poll| + next if poll.has_key?("total_votes") + poll["total_votes"] = poll["voters"] + poll.delete("voters") + end + pcf.value = polls.to_json + pcf.save + end + end + +end diff --git a/plugins/poll/plugin.rb b/plugins/poll/plugin.rb index 853e39cde..3155d20b2 100644 --- a/plugins/poll/plugin.rb +++ b/plugins/poll/plugin.rb @@ -57,7 +57,7 @@ after_initialize do vote = votes[poll_name] || [] # increment counters only when the user hasn't casted a vote yet - poll["total_votes"] += 1 if vote.size == 0 + poll["voters"] += 1 if vote.size == 0 poll["options"].each do |option| option["votes"] -= 1 if vote.include?(option["id"]) @@ -116,7 +116,7 @@ after_initialize do # extract polls parsed.css("div.poll").each do |p| - poll = { "options" => [], "total_votes" => 0 } + poll = { "options" => [], "voters" => 0 } # extract attributes p.attributes.values.each do |attribute| @@ -208,9 +208,10 @@ after_initialize do # only care when raw has changed! return unless self.raw_changed? - extracted_polls = DiscoursePoll::Poll::extract(self.raw, self.topic_id) polls = {} + extracted_polls = DiscoursePoll::Poll::extract(self.raw, self.topic_id) + extracted_polls.each do |poll| # polls should have a unique name if polls.has_key?(poll["name"]) @@ -288,7 +289,7 @@ after_initialize do next unless previous_polls.has_key?(poll_name) next unless polls[poll_name]["options"].size == previous_polls[poll_name]["options"].size - polls[poll_name]["total_votes"] = previous_polls[poll_name]["total_votes"] + polls[poll_name]["voters"] = previous_polls[poll_name]["voters"] for o in 0...polls[poll_name]["options"].size polls[poll_name]["options"][o]["votes"] = previous_polls[poll_name]["options"][o]["votes"] end diff --git a/plugins/poll/spec/controllers/polls_controller_spec.rb b/plugins/poll/spec/controllers/polls_controller_spec.rb index ab9081285..54ee2c4d2 100644 --- a/plugins/poll/spec/controllers/polls_controller_spec.rb +++ b/plugins/poll/spec/controllers/polls_controller_spec.rb @@ -17,7 +17,7 @@ describe ::DiscoursePoll::PollsController do expect(response).to be_success json = ::JSON.parse(response.body) expect(json["poll"]["name"]).to eq("poll") - expect(json["poll"]["total_votes"]).to eq(1) + expect(json["poll"]["voters"]).to eq(1) expect(json["vote"]).to eq(["5c24fc1df56d764b550ceae1b9319125"]) end @@ -36,7 +36,7 @@ describe ::DiscoursePoll::PollsController do xhr :put, :vote, { post_id: poll.id, poll_name: "poll", options: ["e89dec30bbd9bf50fabf6a05b4324edf"] } expect(response).to be_success json = ::JSON.parse(response.body) - expect(json["poll"]["total_votes"]).to eq(1) + expect(json["poll"]["voters"]).to eq(1) expect(json["poll"]["options"][0]["votes"]).to eq(0) expect(json["poll"]["options"][1]["votes"]).to eq(1) end diff --git a/spec/components/new_post_manager_spec.rb b/spec/components/new_post_manager_spec.rb index abc03a9de..bf09d88e6 100644 --- a/spec/components/new_post_manager_spec.rb +++ b/spec/components/new_post_manager_spec.rb @@ -17,6 +17,27 @@ describe NewPostManager do end end + context "default action" do + let(:other_user) { Fabricate(:user) } + + it "doesn't enqueue private messages" do + manager = NewPostManager.new(topic.user, + raw: 'this is a new post', + title: 'this is a new title', + archetype: Archetype.private_message, + target_usernames: other_user.username) + + SiteSetting.approve_unless_trust_level = 4 + result = manager.perform + + expect(result.action).to eq(:create_post) + expect(result).to be_success + expect(result.post).to be_present + expect(result.post.topic.private_message?).to eq(true) + expect(result.post).to be_a(Post) + end + end + context "default handler" do let(:manager) { NewPostManager.new(topic.user, raw: 'this is new post content', topic_id: topic.id) } @@ -54,6 +75,7 @@ describe NewPostManager do expect(result.action).to eq(:enqueued) end end + end context "extensibility priority" do diff --git a/spec/mailers/rejection_mailer_spec.rb b/spec/mailers/rejection_mailer_spec.rb new file mode 100644 index 000000000..141400090 --- /dev/null +++ b/spec/mailers/rejection_mailer_spec.rb @@ -0,0 +1,29 @@ +require "spec_helper" + +describe RejectionMailer do + + describe "send_rejection" do + + context 'sends rejection email' do + let (:user) { Fabricate(:user) } + let (:template_args) { {former_title: "Mail Subject", destination: user.email, site_name: SiteSetting.title} } + let (:reject_mail) { RejectionMailer.send_rejection("email_reject_topic_not_found", user.email, template_args) } + + it 'renders the senders email' do + expect(reject_mail.to).to eql([user.email]) + end + + it 'renders the subject' do + expect(reject_mail.subject).to be_present + end + + it 'renders site title in subject' do + expect(reject_mail.subject).to match(SiteSetting.title) + end + + it 'renders the body' do + expect(reject_mail.body).to be_present + end + end + end +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index a85f0600e..58a48f71d 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -45,13 +45,20 @@ describe User do let(:user) { Fabricate(:user) } let(:admin) { Fabricate(:admin) } - it "enqueues a 'signup after approval' email" do + it "enqueues a 'signup after approval' email if must_approve_users is true" do + SiteSetting.stubs(:must_approve_users).returns(true) Jobs.expects(:enqueue).with( :user_email, has_entries(type: :signup_after_approval) ) user.approve(admin) end + it "doesn't enqueue a 'signup after approval' email if must_approve_users is false" do + SiteSetting.stubs(:must_approve_users).returns(false) + Jobs.expects(:enqueue).never + user.approve(admin) + end + context 'after approval' do before do user.approve(admin)