mirror of
https://github.com/discourse/discourse.git
synced 2025-02-21 14:34:59 +08:00
Merge branch 'master' of github.com:discourse/discourse
This commit is contained in:
commit
7bcf1c5aaa
@ -13,18 +13,6 @@ Discourse.URL = Em.Object.createWithMixins({
|
||||
// Used for matching a /more URL
|
||||
MORE_REGEXP: /\/more$/,
|
||||
|
||||
/**
|
||||
@private
|
||||
|
||||
Get a handle on the application's router. Note that currently it uses `__container__` which is not
|
||||
advised but there is no other way to access the router.
|
||||
|
||||
@method router
|
||||
**/
|
||||
router: function() {
|
||||
return Discourse.__container__.lookup('router:main');
|
||||
}.property(),
|
||||
|
||||
/**
|
||||
Browser aware replaceState. Will only be invoked if the browser supports it.
|
||||
|
||||
@ -70,11 +58,65 @@ Discourse.URL = Em.Object.createWithMixins({
|
||||
path = path.replace(rootURL, '');
|
||||
}
|
||||
|
||||
/*
|
||||
If the URL is in the topic form, /t/something/:topic_id/:post_number
|
||||
then we want to apply some special logic. If the post_number changes within the
|
||||
same topic, use replaceState and instruct our controller to load more posts.
|
||||
*/
|
||||
// TODO: Extract into rules we can inject into the URL handler
|
||||
if (this.navigatedToHome(oldPath, path)) { return; }
|
||||
if (this.navigatedToListMore(oldPath, path)) { return; }
|
||||
if (this.navigatedToHome(oldPath, path)) { return; }
|
||||
|
||||
// Be wary of looking up the router. In this case, we have links in our
|
||||
// HTML, say form compiled markdown posts, that need to be routed.
|
||||
var router = this.get('router');
|
||||
router.router.updateURL(path);
|
||||
return router.handleURL(path);
|
||||
},
|
||||
|
||||
/**
|
||||
Replaces the query parameters in the URL. Use no parameters to clear them.
|
||||
|
||||
@method replaceQueryParams
|
||||
**/
|
||||
queryParams: Em.computed.alias('router.location.queryParams'),
|
||||
|
||||
/**
|
||||
Redirect to a URL.
|
||||
This has been extracted so it can be tested.
|
||||
|
||||
@method redirectTo
|
||||
**/
|
||||
redirectTo: function(url) {
|
||||
window.location = Discourse.getURL(url);
|
||||
},
|
||||
|
||||
/**
|
||||
@private
|
||||
|
||||
If we're viewing more topics, scroll to where we were previously.
|
||||
|
||||
@method navigatedToListMore
|
||||
@param {String} oldPath the previous path we were on
|
||||
@param {String} path the path we're navigating to
|
||||
**/
|
||||
navigatedToListMore: function(oldPath, path) {
|
||||
// If we transition from a /more path, scroll to the top
|
||||
if (this.MORE_REGEXP.exec(oldPath) && (oldPath.indexOf(path) === 0)) {
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
@private
|
||||
|
||||
If the URL is in the topic form, /t/something/:topic_id/:post_number
|
||||
then we want to apply some special logic. If the post_number changes within the
|
||||
same topic, use replaceState and instruct our controller to load more posts.
|
||||
|
||||
@method navigatedToPost
|
||||
@param {String} oldPath the previous path we were on
|
||||
@param {String} path the path we're navigating to
|
||||
**/
|
||||
navigatedToPost: function(oldPath, path) {
|
||||
|
||||
var newMatches = this.TOPIC_REGEXP.exec(path),
|
||||
newTopicId = newMatches ? newMatches[2] : null;
|
||||
|
||||
@ -99,28 +141,33 @@ Discourse.URL = Em.Object.createWithMixins({
|
||||
});
|
||||
|
||||
// Abort routing, we have replaced our state.
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If we transition from a /more path, scroll to the top
|
||||
if (this.MORE_REGEXP.exec(oldPath) && (oldPath.indexOf(path) === 0)) {
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
|
||||
// Be wary of looking up the router. In this case, we have links in our
|
||||
// HTML, say form compiled markdown posts, that need to be routed.
|
||||
var router = this.get('router');
|
||||
router.router.updateURL(path);
|
||||
return router.handleURL(path);
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
Replaces the query parameters in the URL. Use no parameters to clear them.
|
||||
@private
|
||||
|
||||
@method replaceQueryParams
|
||||
Handle the custom case of routing to the root path from itself.
|
||||
|
||||
@param {String} oldPath the previous path we were on
|
||||
@param {String} path the path we're navigating to
|
||||
**/
|
||||
queryParams: Em.computed.alias('router.location.queryParams'),
|
||||
navigatedToHome: function(oldPath, path) {
|
||||
|
||||
var defaultFilter = "/" + Discourse.ListController.filters[0];
|
||||
|
||||
if (path === "/" && (oldPath === "/" || oldPath === defaultFilter)) {
|
||||
// Refresh our list
|
||||
this.controllerFor('list').refresh();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
@private
|
||||
@ -137,13 +184,27 @@ Discourse.URL = Em.Object.createWithMixins({
|
||||
/**
|
||||
@private
|
||||
|
||||
Redirect to a URL.
|
||||
This has been extracted so it can be tested.
|
||||
Get a handle on the application's router. Note that currently it uses `__container__` which is not
|
||||
advised but there is no other way to access the router.
|
||||
|
||||
@method redirectTo
|
||||
@property router
|
||||
**/
|
||||
redirectTo: function(url) {
|
||||
window.location = Discourse.getURL(url);
|
||||
router: function() {
|
||||
return Discourse.__container__.lookup('router:main');
|
||||
}.property(),
|
||||
|
||||
/**
|
||||
@private
|
||||
|
||||
Get a controller. Note that currently it uses `__container__` which is not
|
||||
advised but there is no other way to access the router.
|
||||
|
||||
@method controllerFor
|
||||
@param {String} name the name of the controller
|
||||
**/
|
||||
controllerFor: function(name) {
|
||||
return Discourse.__container__.lookup('controller:' + name);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
@ -172,6 +172,11 @@ Discourse.Utilities = {
|
||||
return false;
|
||||
} else if (files.length > 0) {
|
||||
var upload = files[0];
|
||||
// ensures that new users can upload image
|
||||
if (Discourse.User.current('trust_level') === 0 && Discourse.SiteSettings.newuser_max_images === 0) {
|
||||
bootbox.alert(Em.String.i18n('post.errors.upload_not_allowed_for_new_user'));
|
||||
return false;
|
||||
}
|
||||
// if the image was pasted, sets its name to a default one
|
||||
if (upload instanceof Blob && !(upload instanceof File) && upload.type === "image/png") { upload.name = "blob.png"; }
|
||||
// check that the uploaded file is authorized
|
||||
|
@ -24,6 +24,19 @@ Discourse.ListController = Discourse.Controller.extend({
|
||||
});
|
||||
}.property(),
|
||||
|
||||
/**
|
||||
Refresh our current topic list
|
||||
|
||||
@method refresh
|
||||
**/
|
||||
refresh: function() {
|
||||
var listTopicsController = this.get('controllers.listTopics');
|
||||
listTopicsController.set('model.loaded', false);
|
||||
this.load(this.get('filterMode')).then(function (topicList) {
|
||||
listTopicsController.set('model', topicList);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
Load a list based on a filter
|
||||
|
||||
|
@ -20,7 +20,7 @@ Discourse.StaticController = Discourse.Controller.extend({
|
||||
text = text[1];
|
||||
this.set('content', text);
|
||||
} else {
|
||||
return Discourse.ajax(path + ".json", {dataType: 'html'}).then(function (result) {
|
||||
return Discourse.ajax(path).then(function (result) {
|
||||
staticController.set('content', result);
|
||||
});
|
||||
}
|
||||
|
@ -17,13 +17,18 @@ Discourse.UserStream = Discourse.Model.extend({
|
||||
}.observes('filter'),
|
||||
|
||||
findItems: function() {
|
||||
var url = Discourse.getURL("/user_actions?offset=") + this.get('itemsLoaded') + "&username=" + (this.get('user.username_lower'));
|
||||
var me = this;
|
||||
if(this.get("loading")) { return; }
|
||||
this.set("loading",true);
|
||||
|
||||
var url = Discourse.getURL("/user_actions.json?offset=") + this.get('itemsLoaded') + "&username=" + (this.get('user.username_lower'));
|
||||
if (this.get('filter')) {
|
||||
url += "&filter=" + (this.get('filter'));
|
||||
}
|
||||
|
||||
var stream = this;
|
||||
return Discourse.ajax(url, {cache: 'false'}).then( function(result) {
|
||||
me.set("loading",false);
|
||||
if (result && result.user_actions) {
|
||||
var copy = Em.A();
|
||||
_.each(result.user_actions,function(action) {
|
||||
@ -33,7 +38,7 @@ Discourse.UserStream = Discourse.Model.extend({
|
||||
stream.get('content').pushObjects(copy);
|
||||
stream.set('itemsLoaded', stream.get('itemsLoaded') + result.user_actions.length);
|
||||
}
|
||||
});
|
||||
}, function(){ me.set("loading", false); });
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -31,7 +31,7 @@ Discourse.FilteredListRoute = Discourse.Route.extend({
|
||||
var listTopicsController = this.controllerFor('listTopics');
|
||||
listController.set('filterMode', this.filter);
|
||||
|
||||
var listContent = listTopicsController.get('content');
|
||||
var listContent = listTopicsController.get('model');
|
||||
if (listContent) {
|
||||
listContent.set('loaded', false);
|
||||
}
|
||||
@ -39,7 +39,7 @@ Discourse.FilteredListRoute = Discourse.Route.extend({
|
||||
listController.load(this.filter).then(function(topicList) {
|
||||
listController.set('category', null);
|
||||
listController.set('canCreateTopic', topicList.get('can_create_topic'));
|
||||
listTopicsController.set('content', topicList);
|
||||
listTopicsController.set('model', topicList);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -255,7 +255,6 @@ Discourse.TopicView = Discourse.View.extend(Discourse.Scrolling, {
|
||||
@method updatePosition
|
||||
**/
|
||||
updatePosition: function() {
|
||||
|
||||
this.processSeenPosts();
|
||||
|
||||
var offset = window.pageYOffset || $('html').scrollTop();
|
||||
@ -277,7 +276,10 @@ Discourse.TopicView = Discourse.View.extend(Discourse.Scrolling, {
|
||||
// Dock the counter if necessary
|
||||
var $lastPost = $('article[data-post-id=' + topic.get('postStream.lastPostId') + "]");
|
||||
var lastPostOffset = $lastPost.offset();
|
||||
if (!lastPostOffset) { return; }
|
||||
if (!lastPostOffset) {
|
||||
this.set('controller.dockedCounter', false);
|
||||
return;
|
||||
}
|
||||
this.set('controller.dockedCounter', (offset >= (lastPostOffset.top + $lastPost.height()) - $(window).height()));
|
||||
},
|
||||
|
||||
|
@ -140,9 +140,22 @@ class Users::OmniauthCallbacksController < ApplicationController
|
||||
|
||||
def create_or_sign_on_user_using_cas(auth_token)
|
||||
logger.error "authtoken #{auth_token}"
|
||||
email = "#{auth_token[:extra][:user]}@#{SiteSetting.cas_domainname}"
|
||||
|
||||
email = auth_token[:info][:email] if auth_token[:info]
|
||||
email ||= if SiteSetting.cas_domainname.present?
|
||||
"#{auth_token[:extra][:user]}@#{SiteSetting.cas_domainname}"
|
||||
else
|
||||
auth_token[:extra][:user]
|
||||
end
|
||||
|
||||
username = auth_token[:extra][:user]
|
||||
name = auth_token["uid"]
|
||||
|
||||
name = if auth_token[:info] && auth_token[:info][:name]
|
||||
auth_token[:info][:name]
|
||||
else
|
||||
auth_token["uid"]
|
||||
end
|
||||
|
||||
cas_user_id = auth_token["uid"]
|
||||
|
||||
session[:authentication] = {
|
||||
|
@ -3,7 +3,6 @@ class IncomingLink < ActiveRecord::Base
|
||||
belongs_to :user
|
||||
|
||||
validates :url, presence: true
|
||||
|
||||
validate :referer_valid
|
||||
|
||||
before_validation :extract_domain
|
||||
@ -40,7 +39,8 @@ class IncomingLink < ActiveRecord::Base
|
||||
# Internal: Extract the domain from link.
|
||||
def extract_domain
|
||||
if referer.present?
|
||||
self.domain = URI.parse(referer).host
|
||||
self.domain = URI.parse(self.referer).host
|
||||
self.referer = nil unless self.domain
|
||||
end
|
||||
end
|
||||
|
||||
@ -50,6 +50,7 @@ class IncomingLink < ActiveRecord::Base
|
||||
parsed = URI.parse(url)
|
||||
|
||||
begin
|
||||
# TODO achieve same thing with no exception
|
||||
params = Rails.application.routes.recognize_path(parsed.path)
|
||||
self.topic_id = params[:topic_id]
|
||||
self.post_number = params[:post_number]
|
||||
|
@ -205,7 +205,7 @@ class SiteSetting < ActiveRecord::Base
|
||||
setting(:max_word_length, 30)
|
||||
|
||||
setting(:newuser_max_links, 2)
|
||||
setting(:newuser_max_images, 0)
|
||||
client_setting(:newuser_max_images, 0)
|
||||
|
||||
setting(:newuser_spam_host_threshold, 3)
|
||||
|
||||
|
@ -34,6 +34,11 @@ class Upload < ActiveRecord::Base
|
||||
return unless width > SiteSetting.auto_link_images_wider_than
|
||||
return if has_thumbnail?
|
||||
thumbnail = OptimizedImage.create_for(self, width, height)
|
||||
# TODO: @regis we may want to do the more cleanly, create_for may change the dimensions
|
||||
# this avoids a duplicate key, it should be done more cleanly, this is cheating
|
||||
thumbnail.width = width
|
||||
thumbnail.height = height
|
||||
|
||||
optimized_images << thumbnail if thumbnail
|
||||
end
|
||||
|
||||
|
@ -6,6 +6,7 @@ development:
|
||||
pool: 5
|
||||
timeout: 5000
|
||||
host_names:
|
||||
# /!\ Make sure you *also* restart sidekiq if you change this setting /!\
|
||||
- "localhost"
|
||||
|
||||
# Warning: The database defined as "test" will be erased and
|
||||
@ -29,6 +30,7 @@ production:
|
||||
pool: 5
|
||||
timeout: 5000
|
||||
host_names:
|
||||
# /!\ Make sure you *also* restart sidekiq if you change this setting /!\
|
||||
- production.localhost # Update this to be the domain of your production site
|
||||
|
||||
profile:
|
||||
|
@ -8,6 +8,7 @@ production:
|
||||
timeout: 5000
|
||||
# db_id: 0 # database ID if hosting multiple sites
|
||||
host_names:
|
||||
# /!\ Make sure you *also* restart sidekiq if you change this setting /!\
|
||||
- production.localhost # Update this to be the domain of your production site
|
||||
|
||||
test:
|
||||
|
@ -746,6 +746,7 @@ en:
|
||||
upload_too_large: "Sorry, the file you are trying to upload is too big (maximum size is {{max_size_kb}}kb), please resize it and try again."
|
||||
too_many_uploads: "Sorry, you can only upload one file at a time."
|
||||
upload_not_authorized: "Sorry, the file you are trying to upload is not authorized (authorized extension: {{authorized_extensions}})."
|
||||
upload_not_allowed_for_new_user: "Sorry, new users can not upload images."
|
||||
|
||||
abandon: "Are you sure you want to abandon your post?"
|
||||
|
||||
|
@ -729,6 +729,7 @@ fr:
|
||||
upload_too_large: "Désolé, le fichier que vous êtes en train d'envoyer est trop grand (maximum {{max_size_kb}}Kb). Merci de le redimensionner et de réessayer."
|
||||
too_many_uploads: "Désolé, vous ne pouvez envoyer qu'un seul fichier à la fois."
|
||||
upload_not_authorized: "Désole, le fichier que vous êtes en train d'uploader n'est pas autorisé (extensions autorisées : {{authorized_extensions}})."
|
||||
upload_not_allowed_for_new_user: "Désolé, les nouveaux utilisateurs ne peuvent pas uploader d'images."
|
||||
|
||||
abandon: "Voulez-vous vraiment abandonner ce message ?"
|
||||
|
||||
|
@ -2,9 +2,9 @@ module Jobs
|
||||
class CloseTopic < Jobs::Base
|
||||
|
||||
def execute(args)
|
||||
topic = Topic.find(args[:topic_id])
|
||||
topic = Topic.where(id: args[:topic_id]).first
|
||||
if topic and topic.auto_close_at and !topic.closed? and !topic.deleted_at
|
||||
closer = User.find(args[:user_id])
|
||||
closer = User.where(id: args[:user_id]).first
|
||||
if Guardian.new(closer).can_moderate?(topic)
|
||||
topic.update_status('autoclosed', true, closer)
|
||||
end
|
||||
|
50
lib/tasks/integration.rake
Normal file
50
lib/tasks/integration.rake
Normal file
@ -0,0 +1,50 @@
|
||||
require 'open-uri'
|
||||
|
||||
desc 'Creates the integration fixtures. Requires a development instance running.'
|
||||
task 'integration:create_fixtures' => :environment do
|
||||
|
||||
fixtures = {
|
||||
list: ["/latest.json", "/categories.json", "/category/bug.json"],
|
||||
topic: ["/t/280.json"],
|
||||
user: ["/users/eviltrout.json", "/user_actions.json?offset=0&username=eviltrout"],
|
||||
static: ["/faq", '/tos', '/privacy']
|
||||
}
|
||||
|
||||
fixtures.each do |type, urls|
|
||||
|
||||
filename = "#{Rails.root}/test/javascripts/fixtures/#{type}_fixtures.js"
|
||||
|
||||
content = "/*jshint maxlen:10000000 */\n"
|
||||
urls.each do |url|
|
||||
|
||||
http_result = fake_xhr("http://localhost:3000#{url}")
|
||||
|
||||
# If the result is not JSON, convert it to JSON
|
||||
begin
|
||||
parsed = ::JSON.parse(http_result)
|
||||
rescue
|
||||
http_result = http_result.to_json
|
||||
end
|
||||
content << "Discourse.URL_FIXTURES[\"#{url}\"] = #{http_result};\n"
|
||||
|
||||
end
|
||||
|
||||
File.write(filename, content)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def fake_xhr(url)
|
||||
uri = URI(url)
|
||||
|
||||
result = nil
|
||||
Net::HTTP.start(uri.host, uri.port) do |http|
|
||||
request = Net::HTTP::Get.new uri
|
||||
request.add_field "X-Requested-With", "XMLHttpRequest"
|
||||
response = http.request(request)
|
||||
result = response.body.force_encoding("UTF-8")
|
||||
end
|
||||
|
||||
result
|
||||
|
||||
end
|
@ -8,34 +8,39 @@ task 'posts:refresh_oneboxes' => :environment do
|
||||
rebake_posts invalidate_oneboxes: true
|
||||
end
|
||||
|
||||
def rebake_post(post,opts)
|
||||
cooked = post.cook(
|
||||
post.raw,
|
||||
topic_id: post.topic_id,
|
||||
invalidate_oneboxes: opts.fetch(:invalidate_oneboxes, false)
|
||||
)
|
||||
|
||||
if cooked != post.cooked
|
||||
Post.exec_sql(
|
||||
'update posts set cooked = ? where id = ?', cooked, post.id
|
||||
)
|
||||
post.cooked = cooked
|
||||
putc "#"
|
||||
else
|
||||
putc "."
|
||||
end
|
||||
|
||||
TopicLink.extract_from post
|
||||
# make sure we trigger the post process
|
||||
post.trigger_post_process
|
||||
rescue => e
|
||||
puts "\n\nFailed to bake topic_id #{post.topic_id} post_id #{post.id} #{e}\n#{e.backtrace.join("\n")} \n\n"
|
||||
end
|
||||
|
||||
def rebake_posts(opts = {})
|
||||
RailsMultisite::ConnectionManagement.each_connection do |db|
|
||||
puts "Re baking post markdown for #{db} , changes are denoted with # , no change with ."
|
||||
|
||||
total = Post.select([
|
||||
total = 0
|
||||
Post.select([
|
||||
:id, :user_id, :cooked, :raw, :topic_id, :post_number
|
||||
]).inject(0) do |total, post|
|
||||
cooked = post.cook(
|
||||
post.raw,
|
||||
topic_id: post.topic_id,
|
||||
invalidate_oneboxes: opts.fetch(:invalidate_oneboxes, false)
|
||||
)
|
||||
|
||||
if cooked != post.cooked
|
||||
Post.exec_sql(
|
||||
'update posts set cooked = ? where id = ?', cooked, post.id
|
||||
)
|
||||
post.cooked = cooked
|
||||
putc "#"
|
||||
else
|
||||
putc "."
|
||||
end
|
||||
|
||||
TopicLink.extract_from post
|
||||
|
||||
# make sure we trigger the post process
|
||||
post.trigger_post_process
|
||||
|
||||
]).each do |post|
|
||||
rebake_post(post,opts)
|
||||
total += 1
|
||||
end
|
||||
|
||||
|
@ -8,16 +8,16 @@ describe Jobs::CloseTopic do
|
||||
it 'closes a topic that is set to auto-close' do
|
||||
topic = Fabricate.build(:topic, auto_close_at: Time.zone.now, user: admin)
|
||||
topic.expects(:update_status).with('autoclosed', true, admin)
|
||||
Topic.stubs(:find).returns(topic)
|
||||
User.stubs(:find).returns(admin)
|
||||
Topic.stubs(:where).returns([topic])
|
||||
User.stubs(:where).returns([admin])
|
||||
Jobs::CloseTopic.new.execute( topic_id: 123, user_id: 234 )
|
||||
end
|
||||
|
||||
shared_examples_for "cases when CloseTopic does nothing" do
|
||||
it 'does nothing to the topic' do
|
||||
topic.expects(:update_status).never
|
||||
Topic.stubs(:find).returns(topic)
|
||||
User.stubs(:find).returns(admin)
|
||||
Topic.stubs(:where).returns([topic])
|
||||
User.stubs(:where).returns([admin])
|
||||
Jobs::CloseTopic.new.execute( topic_id: 123, user_id: 234 )
|
||||
end
|
||||
end
|
||||
|
@ -3,7 +3,49 @@ require 'spec_helper'
|
||||
describe Users::OmniauthCallbacksController do
|
||||
|
||||
let(:auth) { {info: {email: 'eviltrout@made.up.email', name: 'Robin Ward', uid: 123456789}, "extra" => {"raw_info" => {} } } }
|
||||
let(:cas_auth) {{ uid: "caluser2", extra: {user: "caluser2"} } }
|
||||
let(:cas_auth) { { 'uid' => 'casuser', extra: { user: 'casuser'} } }
|
||||
|
||||
shared_examples_for "an authenticaton provider" do |provider|
|
||||
context "when #{provider} logins are disabled" do
|
||||
before do
|
||||
SiteSetting.stubs("enable_#{provider}_logins?").returns(false)
|
||||
end
|
||||
|
||||
it "fails" do
|
||||
get :complete, provider: provider
|
||||
response.should_not be_success
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "when #{provider} logins are enabled" do
|
||||
before do
|
||||
SiteSetting.stubs("enable_#{provider}_logins?").returns(true)
|
||||
end
|
||||
|
||||
it "succeeds" do
|
||||
get :complete, provider: provider
|
||||
response.should be_success
|
||||
end
|
||||
|
||||
context "and 'invite only' site setting is enabled" do
|
||||
before do
|
||||
SiteSetting.stubs(:invite_only?).returns(true)
|
||||
end
|
||||
|
||||
it "informs the user they are awaiting approval" do
|
||||
xhr :get, :complete, provider: provider, format: :json
|
||||
|
||||
expect(
|
||||
JSON.parse(response.body)['awaiting_approval']
|
||||
).to be_true
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe 'invalid provider' do
|
||||
|
||||
it "fails" do
|
||||
@ -20,29 +62,8 @@ describe Users::OmniauthCallbacksController do
|
||||
request.env["omniauth.auth"] = auth
|
||||
end
|
||||
|
||||
it "fails when twitter logins are disabled" do
|
||||
SiteSetting.stubs(:enable_twitter_logins?).returns(false)
|
||||
get :complete, provider: 'twitter'
|
||||
response.should_not be_success
|
||||
end
|
||||
it_behaves_like "an authenticaton provider", 'twitter'
|
||||
|
||||
it "succeeds when twitter logins are enabled" do
|
||||
SiteSetting.stubs(:enable_twitter_logins?).returns(true)
|
||||
get :complete, provider: 'twitter'
|
||||
response.should be_success
|
||||
end
|
||||
|
||||
context "when 'invite only' site setting is enabled" do
|
||||
before { SiteSetting.stubs(:invite_only?).returns(true) }
|
||||
|
||||
it 'informs the user they are awaiting approval' do
|
||||
xhr :get, :complete, provider: 'twitter', format: :json
|
||||
|
||||
expect(
|
||||
JSON.parse(response.body)['awaiting_approval']
|
||||
).to be_true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'facebook' do
|
||||
@ -51,17 +72,7 @@ describe Users::OmniauthCallbacksController do
|
||||
request.env["omniauth.auth"] = auth
|
||||
end
|
||||
|
||||
it "fails when facebook logins are disabled" do
|
||||
SiteSetting.stubs(:enable_facebook_logins?).returns(false)
|
||||
get :complete, provider: 'facebook'
|
||||
response.should_not be_success
|
||||
end
|
||||
|
||||
it "succeeds when facebook logins are enabled" do
|
||||
SiteSetting.stubs(:enable_facebook_logins?).returns(true)
|
||||
get :complete, provider: 'facebook'
|
||||
response.should be_success
|
||||
end
|
||||
it_behaves_like "an authenticaton provider", 'facebook'
|
||||
|
||||
end
|
||||
|
||||
@ -71,16 +82,47 @@ describe Users::OmniauthCallbacksController do
|
||||
request.env["omniauth.auth"] = cas_auth
|
||||
end
|
||||
|
||||
it "fails when cas logins are disabled" do
|
||||
SiteSetting.stubs(:enable_cas_logins?).returns(false)
|
||||
get :complete, provider: 'cas'
|
||||
response.should_not be_success
|
||||
end
|
||||
it_behaves_like "an authenticaton provider", 'cas'
|
||||
|
||||
describe "extracted user data" do
|
||||
before do
|
||||
SiteSetting.stubs(:enable_cas_logins?).returns(true)
|
||||
end
|
||||
|
||||
subject {
|
||||
xhr :get, :complete, provider: 'cas', format: :json
|
||||
OpenStruct.new(JSON.parse(response.body))
|
||||
}
|
||||
|
||||
context "when no user infos are returned by cas" do
|
||||
its(:username) { should eq 'casuser' }
|
||||
its(:name) { should eq 'casuser' }
|
||||
its(:email) { should eq 'casuser' } # No cas_domainname configured!
|
||||
|
||||
context "when cas_domainname is configured" do
|
||||
before do
|
||||
SiteSetting.stubs(:cas_domainname).returns("example.com")
|
||||
end
|
||||
|
||||
its(:email) { should eq 'casuser@example.com' }
|
||||
end
|
||||
end
|
||||
|
||||
context "when user infos are returned by cas" do
|
||||
before do
|
||||
request.env["omniauth.auth"] = cas_auth.merge({
|
||||
info: {
|
||||
name: 'Proper Name',
|
||||
email: 'public@example.com'
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
its(:username) { should eq 'casuser' }
|
||||
its(:name) { should eq 'Proper Name' }
|
||||
its(:email) { should eq 'public@example.com' }
|
||||
end
|
||||
|
||||
it "succeeds when cas logins are enabled" do
|
||||
SiteSetting.stubs(:enable_cas_logins?).returns(true)
|
||||
get :complete, provider: 'cas'
|
||||
response.should be_success
|
||||
end
|
||||
|
||||
end
|
||||
@ -93,31 +135,11 @@ describe Users::OmniauthCallbacksController do
|
||||
end
|
||||
|
||||
describe "google" do
|
||||
it "fails when google logins are disabled" do
|
||||
SiteSetting.stubs(:enable_google_logins?).returns(false)
|
||||
get :complete, provider: 'google'
|
||||
response.should_not be_success
|
||||
end
|
||||
|
||||
it "succeeds when google logins are enabled" do
|
||||
SiteSetting.stubs(:enable_google_logins?).returns(true)
|
||||
get :complete, provider: 'google'
|
||||
response.should be_success
|
||||
end
|
||||
it_behaves_like "an authenticaton provider", 'google'
|
||||
end
|
||||
|
||||
describe "yahoo" do
|
||||
it "fails when yahoo logins are disabled" do
|
||||
SiteSetting.stubs(:enable_yahoo_logins?).returns(false)
|
||||
get :complete, provider: 'yahoo'
|
||||
response.should_not be_success
|
||||
end
|
||||
|
||||
it "succeeds when yahoo logins are enabled" do
|
||||
SiteSetting.stubs(:enable_yahoo_logins?).returns(true)
|
||||
get :complete, provider: 'yahoo'
|
||||
response.should be_success
|
||||
end
|
||||
it_behaves_like "an authenticaton provider", 'yahoo'
|
||||
end
|
||||
|
||||
end
|
||||
@ -128,17 +150,7 @@ describe Users::OmniauthCallbacksController do
|
||||
request.env["omniauth.auth"] = auth
|
||||
end
|
||||
|
||||
it "fails when github logins are disabled" do
|
||||
SiteSetting.stubs(:enable_github_logins?).returns(false)
|
||||
get :complete, provider: 'github'
|
||||
response.should_not be_success
|
||||
end
|
||||
|
||||
it "succeeds when github logins are enabled" do
|
||||
SiteSetting.stubs(:enable_github_logins?).returns(true)
|
||||
get :complete, provider: 'github'
|
||||
response.should be_success
|
||||
end
|
||||
it_behaves_like "an authenticaton provider", 'github'
|
||||
|
||||
end
|
||||
|
||||
@ -148,17 +160,7 @@ describe Users::OmniauthCallbacksController do
|
||||
request.env["omniauth.auth"] = auth
|
||||
end
|
||||
|
||||
it "fails when persona logins are disabled" do
|
||||
SiteSetting.stubs(:enable_persona_logins?).returns(false)
|
||||
get :complete, provider: 'persona'
|
||||
response.should_not be_success
|
||||
end
|
||||
|
||||
it "succeeds when persona logins are enabled" do
|
||||
SiteSetting.stubs(:enable_persona_logins?).returns(true)
|
||||
get :complete, provider: 'persona'
|
||||
response.should be_success
|
||||
end
|
||||
it_behaves_like "an authenticaton provider", 'persona'
|
||||
|
||||
end
|
||||
|
||||
|
@ -48,6 +48,10 @@ describe IncomingLink do
|
||||
TestRequest.new(env)
|
||||
end
|
||||
|
||||
it "does not explode with bad referer" do
|
||||
IncomingLink.add(req('http://sam.com','file:///Applications/Install/75067ABC-C9D1-47B7-8ACE-76AEDE3911B2/Install/'))
|
||||
end
|
||||
|
||||
it "does nothing if referer is empty" do
|
||||
IncomingLink.expects(:create).never
|
||||
IncomingLink.add(req('http://somesite.com'))
|
||||
|
@ -23,6 +23,15 @@ test("uploading one file", function() {
|
||||
ok(bootbox.alert.calledWith(Em.String.i18n('post.errors.too_many_uploads')));
|
||||
});
|
||||
|
||||
test("new user", function() {
|
||||
Discourse.SiteSettings.newuser_max_images = 0;
|
||||
this.stub(Discourse.User, 'current').withArgs("trust_level").returns(0);
|
||||
this.stub(bootbox, "alert");
|
||||
|
||||
ok(!validUpload([1]));
|
||||
ok(bootbox.alert.calledWith(Em.String.i18n('post.errors.upload_not_allowed_for_new_user')));
|
||||
});
|
||||
|
||||
test("ensures an authorized upload", function() {
|
||||
var html = { name: "unauthorized.html" };
|
||||
var extensions = Discourse.SiteSettings.authorized_extensions.replace(/\|/g, ", ");
|
||||
|
File diff suppressed because one or more lines are too long
4
test/javascripts/fixtures/static_fixtures.js
Normal file
4
test/javascripts/fixtures/static_fixtures.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
test/javascripts/fixtures/user_fixtures.js
Normal file
3
test/javascripts/fixtures/user_fixtures.js
Normal file
File diff suppressed because one or more lines are too long
@ -1,5 +1,5 @@
|
||||
function integration(name) {
|
||||
module(name, {
|
||||
module("Integration: " + name, {
|
||||
setup: function() {
|
||||
sinon.stub(Discourse.ScrollingDOMMethods, "bindOnScroll");
|
||||
sinon.stub(Discourse.ScrollingDOMMethods, "unbindOnScroll");
|
||||
|
@ -1,24 +1,29 @@
|
||||
integration("List Topics");
|
||||
|
||||
test("Default List", function() {
|
||||
expect(2);
|
||||
|
||||
visit("/").then(function() {
|
||||
expect(2);
|
||||
|
||||
ok(exists("#topic-list"), "The list of topics was rendered");
|
||||
ok(exists('#topic-list .topic-list-item'), "has topics");
|
||||
});
|
||||
});
|
||||
|
||||
test("List one Category", function() {
|
||||
expect(2);
|
||||
|
||||
visit("/category/bug").then(function() {
|
||||
ok(exists("#topic-list"), "The list of topics was rendered");
|
||||
ok(exists('#topic-list .topic-list-item'), "has topics");
|
||||
});
|
||||
});
|
||||
|
||||
test("Categories List", function() {
|
||||
expect(1);
|
||||
|
||||
visit("/categories").then(function() {
|
||||
expect(1);
|
||||
|
||||
ok(exists('.category-list-item'), "has a list of categories");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
22
test/javascripts/integration/static_test.js
Normal file
22
test/javascripts/integration/static_test.js
Normal file
@ -0,0 +1,22 @@
|
||||
integration("Static");
|
||||
|
||||
test("Faq", function() {
|
||||
expect(1);
|
||||
visit("/faq").then(function() {
|
||||
ok(exists(".body-page"), "The content is present");
|
||||
});
|
||||
});
|
||||
|
||||
test("Terms of Service", function() {
|
||||
expect(1);
|
||||
visit("/tos").then(function() {
|
||||
ok(exists(".body-page"), "The content is present");
|
||||
});
|
||||
});
|
||||
|
||||
test("Privacy", function() {
|
||||
expect(1);
|
||||
visit("/privacy").then(function() {
|
||||
ok(exists(".body-page"), "The content is present");
|
||||
});
|
||||
});
|
12
test/javascripts/integration/user_test.js
Normal file
12
test/javascripts/integration/user_test.js
Normal file
@ -0,0 +1,12 @@
|
||||
integration("User");
|
||||
|
||||
test("Profile", function() {
|
||||
|
||||
visit("/users/eviltrout").then(function() {
|
||||
expect(2);
|
||||
|
||||
ok(exists(".user-heading"), "The heading is rendered");
|
||||
ok(exists("#user-stream"), "The stream is rendered");
|
||||
});
|
||||
|
||||
});
|
@ -1,6 +1,6 @@
|
||||
integration("View Topic");
|
||||
|
||||
test("View a Topic", function() {
|
||||
test("Enter a Topic", function() {
|
||||
|
||||
visit("/t/internationalization-localization/280").then(function() {
|
||||
expect(2);
|
||||
|
@ -70,6 +70,7 @@ d.write('<style>#ember-testing-container { position: absolute; background: white
|
||||
Discourse.rootElement = '#ember-testing';
|
||||
Discourse.setupForTesting();
|
||||
Discourse.injectTestHelpers();
|
||||
Discourse.bindDOMEvents();
|
||||
|
||||
|
||||
Discourse.Router.map(function() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user