Commit 05b6b3868ceed5b14c11afce1068f28fee8488c6
1 parent
493dd777
Exists in
theme-brasil-digital-from-staging
and in
9 other branches
merging with branch AI3033-serpro_integration of rails 2.3
Showing
25 changed files
with
1180 additions
and
40 deletions
Show diff stats
app/controllers/public/account_controller.rb
| @@ -17,6 +17,8 @@ class AccountController < ApplicationController | @@ -17,6 +17,8 @@ class AccountController < ApplicationController | ||
| 17 | @user = User.find_by_activation_code(params[:activation_code]) if params[:activation_code] | 17 | @user = User.find_by_activation_code(params[:activation_code]) if params[:activation_code] |
| 18 | if @user and @user.activate | 18 | if @user and @user.activate |
| 19 | @message = _("Your account has been activated, now you can log in!") | 19 | @message = _("Your account has been activated, now you can log in!") |
| 20 | + check_redirection | ||
| 21 | + session[:join] = params[:join] unless params[:join].blank? | ||
| 20 | render :action => 'login', :userlogin => @user.login | 22 | render :action => 'login', :userlogin => @user.login |
| 21 | else | 23 | else |
| 22 | session[:notice] = _("It looks like you're trying to activate an account. Perhaps have already activated this account?") | 24 | session[:notice] = _("It looks like you're trying to activate an account. Perhaps have already activated this account?") |
| @@ -35,6 +37,7 @@ class AccountController < ApplicationController | @@ -35,6 +37,7 @@ class AccountController < ApplicationController | ||
| 35 | self.current_user ||= User.authenticate(params[:user][:login], params[:user][:password], environment) if params[:user] | 37 | self.current_user ||= User.authenticate(params[:user][:login], params[:user][:password], environment) if params[:user] |
| 36 | 38 | ||
| 37 | if logged_in? | 39 | if logged_in? |
| 40 | + check_join_in_community(self.current_user) | ||
| 38 | if params[:remember_me] == "1" | 41 | if params[:remember_me] == "1" |
| 39 | self.current_user.remember_me | 42 | self.current_user.remember_me |
| 40 | cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at } | 43 | cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at } |
| @@ -91,6 +94,7 @@ class AccountController < ApplicationController | @@ -91,6 +94,7 @@ class AccountController < ApplicationController | ||
| 91 | if session[:may_be_a_bot] | 94 | if session[:may_be_a_bot] |
| 92 | return false unless verify_recaptcha :model=>@user, :message=>_('Captcha (the human test)') | 95 | return false unless verify_recaptcha :model=>@user, :message=>_('Captcha (the human test)') |
| 93 | end | 96 | end |
| 97 | + @user.community_to_join = session[:join] | ||
| 94 | @user.signup! | 98 | @user.signup! |
| 95 | owner_role = Role.find_by_name('owner') | 99 | owner_role = Role.find_by_name('owner') |
| 96 | @user.person.affiliate(@user.person, [owner_role]) if owner_role | 100 | @user.person.affiliate(@user.person, [owner_role]) if owner_role |
| @@ -101,6 +105,7 @@ class AccountController < ApplicationController | @@ -101,6 +105,7 @@ class AccountController < ApplicationController | ||
| 101 | end | 105 | end |
| 102 | if @user.activated? | 106 | if @user.activated? |
| 103 | self.current_user = @user | 107 | self.current_user = @user |
| 108 | + check_join_in_community(@user) | ||
| 104 | go_to_signup_initial_page | 109 | go_to_signup_initial_page |
| 105 | else | 110 | else |
| 106 | @register_pending = true | 111 | @register_pending = true |
| @@ -388,12 +393,6 @@ class AccountController < ApplicationController | @@ -388,12 +393,6 @@ class AccountController < ApplicationController | ||
| 388 | end | 393 | end |
| 389 | 394 | ||
| 390 | def go_to_initial_page | 395 | def go_to_initial_page |
| 391 | - if params[:redirection] | ||
| 392 | - session[:return_to] = @user.return_to | ||
| 393 | - @user.return_to = nil | ||
| 394 | - @user.save | ||
| 395 | - end | ||
| 396 | - | ||
| 397 | if params[:return_to] | 396 | if params[:return_to] |
| 398 | redirect_to params[:return_to] | 397 | redirect_to params[:return_to] |
| 399 | elsif environment.enabled?('allow_change_of_redirection_after_login') | 398 | elsif environment.enabled?('allow_change_of_redirection_after_login') |
| @@ -444,4 +443,19 @@ class AccountController < ApplicationController | @@ -444,4 +443,19 @@ class AccountController < ApplicationController | ||
| 444 | redirect_back_or_default(default) | 443 | redirect_back_or_default(default) |
| 445 | end | 444 | end |
| 446 | end | 445 | end |
| 446 | + | ||
| 447 | + def check_redirection | ||
| 448 | + unless params[:redirection].blank? | ||
| 449 | + session[:return_to] = @user.return_to | ||
| 450 | + @user.update_attributes(:return_to => nil) | ||
| 451 | + end | ||
| 452 | + end | ||
| 453 | + | ||
| 454 | + def check_join_in_community(user) | ||
| 455 | + profile_to_join = session[:join] | ||
| 456 | + unless profile_to_join.blank? | ||
| 457 | + environment.profiles.find_by_identifier(profile_to_join).add_member(user.person) | ||
| 458 | + session.delete(:join) | ||
| 459 | + end | ||
| 460 | + end | ||
| 447 | end | 461 | end |
app/controllers/public/profile_controller.rb
| @@ -3,7 +3,7 @@ class ProfileController < PublicController | @@ -3,7 +3,7 @@ class ProfileController < PublicController | ||
| 3 | needs_profile | 3 | needs_profile |
| 4 | before_filter :check_access_to_profile, :except => [:join, :join_not_logged, :index, :add] | 4 | before_filter :check_access_to_profile, :except => [:join, :join_not_logged, :index, :add] |
| 5 | before_filter :store_location, :only => [:join, :join_not_logged, :report_abuse, :send_mail] | 5 | before_filter :store_location, :only => [:join, :join_not_logged, :report_abuse, :send_mail] |
| 6 | - before_filter :login_required, :only => [:add, :join, :join_not_logged, :leave, :unblock, :leave_scrap, :remove_scrap, :remove_activity, :view_more_activities, :view_more_network_activities, :report_abuse, :register_report, :leave_comment_on_activity, :send_mail] | 6 | + before_filter :login_required, :only => [:add, :join, :leave, :unblock, :leave_scrap, :remove_scrap, :remove_activity, :view_more_activities, :view_more_network_activities, :report_abuse, :register_report, :leave_comment_on_activity, :send_mail] |
| 7 | 7 | ||
| 8 | helper TagsHelper | 8 | helper TagsHelper |
| 9 | 9 | ||
| @@ -97,21 +97,12 @@ class ProfileController < PublicController | @@ -97,21 +97,12 @@ class ProfileController < PublicController | ||
| 97 | end | 97 | end |
| 98 | 98 | ||
| 99 | def join_not_logged | 99 | def join_not_logged |
| 100 | - if request.post? | ||
| 101 | - profile.add_member(user) | ||
| 102 | - session[:notice] = _('%s administrator still needs to accept you as member.') % profile.name if profile.closed? | ||
| 103 | - redirect_to_previous_location | 100 | + session[:join] = profile.identifier |
| 101 | + | ||
| 102 | + if user | ||
| 103 | + redirect_to :controller => 'profile', :action => 'join' | ||
| 104 | else | 104 | else |
| 105 | - if user.memberships.include?(profile) | ||
| 106 | - session[:notice] = _('You are already a member of %s.') % profile.name | ||
| 107 | - redirect_to profile.url | ||
| 108 | - return | ||
| 109 | - end | ||
| 110 | - if request.xhr? | ||
| 111 | - render :layout => false | ||
| 112 | - else | ||
| 113 | - redirect_to profile.url | ||
| 114 | - end | 105 | + redirect_to :controller => '/account', :action => 'login' |
| 115 | end | 106 | end |
| 116 | end | 107 | end |
| 117 | 108 |
app/models/user.rb
| @@ -63,6 +63,9 @@ class User < ActiveRecord::Base | @@ -63,6 +63,9 @@ class User < ActiveRecord::Base | ||
| 63 | self.person.preferred_domain && self.person.preferred_domain.name || self.environment.default_hostname(true) | 63 | self.person.preferred_domain && self.person.preferred_domain.name || self.environment.default_hostname(true) |
| 64 | end | 64 | end |
| 65 | 65 | ||
| 66 | + # virtual attribute used to stash which community to join on signup or login | ||
| 67 | + attr_accessor :community_to_join | ||
| 68 | + | ||
| 66 | class Mailer < ActionMailer::Base | 69 | class Mailer < ActionMailer::Base |
| 67 | def activation_email_notify(user) | 70 | def activation_email_notify(user) |
| 68 | user_email = "#{user.login}@#{user.email_domain}" | 71 | user_email = "#{user.login}@#{user.email_domain}" |
| @@ -85,7 +88,8 @@ class User < ActiveRecord::Base | @@ -85,7 +88,8 @@ class User < ActiveRecord::Base | ||
| 85 | :activation_code => user.activation_code, | 88 | :activation_code => user.activation_code, |
| 86 | :environment => user.environment.name, | 89 | :environment => user.environment.name, |
| 87 | :url => user.environment.top_url, | 90 | :url => user.environment.top_url, |
| 88 | - :redirection => (true if user.return_to) | 91 | + :redirection => (true if user.return_to), |
| 92 | + :join => (user.community_to_join if user.community_to_join) | ||
| 89 | end | 93 | end |
| 90 | 94 | ||
| 91 | def signup_welcome_email(user) | 95 | def signup_welcome_email(user) |
features/login.feature
| @@ -207,3 +207,18 @@ Feature: login | @@ -207,3 +207,18 @@ Feature: login | ||
| 207 | | Password | 123456 | | 207 | | Password | 123456 | |
| 208 | When I press "Log in" | 208 | When I press "Log in" |
| 209 | Then I should be on joaosilva's control panel | 209 | Then I should be on joaosilva's control panel |
| 210 | + | ||
| 211 | + Scenario: join community on login | ||
| 212 | + Given the following users | ||
| 213 | + | login | name | | ||
| 214 | + | mariasilva | Maria Silva | | ||
| 215 | + And the following communities | ||
| 216 | + | name | identifier | owner | | ||
| 217 | + | Free Software | freesoftware | mariasilva | | ||
| 218 | + And I am on /freesoftware | ||
| 219 | + When I follow "Join" | ||
| 220 | + And I fill in the following: | ||
| 221 | + | Username / Email | joaosilva | | ||
| 222 | + | Password | 123456 | | ||
| 223 | + And I press "Log in" | ||
| 224 | + Then "Joao Silva" should be a member of "Free Software" |
features/signup.feature
| @@ -250,3 +250,51 @@ Feature: signup | @@ -250,3 +250,51 @@ Feature: signup | ||
| 250 | And I fill in "Password" with "secret" | 250 | And I fill in "Password" with "secret" |
| 251 | And I press "Log in" | 251 | And I press "Log in" |
| 252 | Then I should be on the homepage | 252 | Then I should be on the homepage |
| 253 | + | ||
| 254 | + @selenium | ||
| 255 | + Scenario: join community on signup | ||
| 256 | + Given the following users | ||
| 257 | + | login | name | | ||
| 258 | + | mariasilva | Maria Silva | | ||
| 259 | + And the following communities | ||
| 260 | + | name | identifier | owner | | ||
| 261 | + | Free Software | freesoftware | mariasilva | | ||
| 262 | + And feature "skip_new_user_email_confirmation" is disabled on environment | ||
| 263 | + And I am on /freesoftware | ||
| 264 | + When I follow "Join" | ||
| 265 | + And I follow "New user" | ||
| 266 | + And I fill in the following within ".no-boxes": | ||
| 267 | + | e-Mail | josesilva@example.com | | ||
| 268 | + | Username | josesilva | | ||
| 269 | + | Password | secret | | ||
| 270 | + | Password confirmation | secret | | ||
| 271 | + | Full name | José da Silva | | ||
| 272 | + And wait for the captcha signup time | ||
| 273 | + And I press "Create my account" | ||
| 274 | + And I go to josesilva's confirmation URL | ||
| 275 | + And I fill in "Username" with "josesilva" | ||
| 276 | + And I fill in "Password" with "secret" | ||
| 277 | + And I press "Log in" | ||
| 278 | + Then "José da Silva" should be a member of "Free Software" | ||
| 279 | + | ||
| 280 | + @selenium | ||
| 281 | + Scenario: join community on direct signup | ||
| 282 | + Given the following users | ||
| 283 | + | login | name | | ||
| 284 | + | mariasilva | Maria Silva | | ||
| 285 | + And the following communities | ||
| 286 | + | name | identifier | owner | | ||
| 287 | + | Free Software | freesoftware | mariasilva | | ||
| 288 | + And feature "skip_new_user_email_confirmation" is enabled on environment | ||
| 289 | + And I am on /freesoftware | ||
| 290 | + When I follow "Join" | ||
| 291 | + And I follow "New user" | ||
| 292 | + And I fill in the following within ".no-boxes": | ||
| 293 | + | e-Mail | josesilva@example.com | | ||
| 294 | + | Username | josesilva | | ||
| 295 | + | Password | secret | | ||
| 296 | + | Password confirmation | secret | | ||
| 297 | + | Full name | José da Silva | | ||
| 298 | + And wait for the captcha signup time | ||
| 299 | + And I press "Create my account" | ||
| 300 | + Then "José da Silva" should be a member of "Free Software" |
plugins/serpro_integration/controllers/serpro_integration_plugin_myprofile_controller.rb
0 → 100644
| @@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
| 1 | +class SerproIntegrationPluginMyprofileController < MyProfileController | ||
| 2 | + append_view_path File.join(File.dirname(__FILE__) + '/../views') | ||
| 3 | + | ||
| 4 | + def create_gitlab | ||
| 5 | + profile.create_gitlab_project | ||
| 6 | + render :update do |page| | ||
| 7 | + page.replace_html 'gitlab', :partial => 'gitlab' | ||
| 8 | +# page.replace_html 'gitlab', 'teste' | ||
| 9 | + end | ||
| 10 | +# raise 'teste my profile' | ||
| 11 | + end | ||
| 12 | + | ||
| 13 | +end |
| @@ -0,0 +1,15 @@ | @@ -0,0 +1,15 @@ | ||
| 1 | +Feature: require authentication to comment | ||
| 2 | + | ||
| 3 | + Background: | ||
| 4 | + Given plugin RequireAuthToCommentPlugin is enabled on environment | ||
| 5 | + And the following users | ||
| 6 | + | login | | ||
| 7 | + | bozo | | ||
| 8 | + | ||
| 9 | + Scenario: enabling unauthenticated comment per profile | ||
| 10 | + Given I am logged in as "bozo" | ||
| 11 | + When I edit my profile | ||
| 12 | + And I check "Accept comments from unauthenticated users" | ||
| 13 | + And I press "Save" | ||
| 14 | + Then I edit my profile | ||
| 15 | + And the "Accept comments from unauthenticated users" checkbox should be checked |
| @@ -0,0 +1,220 @@ | @@ -0,0 +1,220 @@ | ||
| 1 | +require_dependency 'community' | ||
| 2 | +require 'gitlab' | ||
| 3 | +#require 'jenkins_api_client' | ||
| 4 | + | ||
| 5 | +class Community | ||
| 6 | + | ||
| 7 | + settings_items :allow_sonar_integration, :type => :boolean, :default => true | ||
| 8 | + settings_items :allow_gitlab_integration, :type => :boolean, :default => true | ||
| 9 | + settings_items :allow_jenkins_integration, :type => :boolean, :default => true | ||
| 10 | + | ||
| 11 | + #FIXME make test for default option | ||
| 12 | + settings_items :serpro_integration_plugin, :type => Hash, :default => {} | ||
| 13 | + | ||
| 14 | + ########################################## | ||
| 15 | + # Gitlab stuff # | ||
| 16 | + ########################################## | ||
| 17 | + | ||
| 18 | + after_create :create_gitlab_project | ||
| 19 | + | ||
| 20 | + def gitlab= params | ||
| 21 | + self.serpro_integration_plugin[:gitlab] = params | ||
| 22 | + end | ||
| 23 | + | ||
| 24 | + def gitlab | ||
| 25 | + self.serpro_integration_plugin[:gitlab] ||= {} | ||
| 26 | + self.serpro_integration_plugin[:gitlab] | ||
| 27 | + end | ||
| 28 | + | ||
| 29 | + def create_gitlab_project | ||
| 30 | + Gitlab.endpoint = self.gitlab_host | ||
| 31 | + Gitlab.private_token = self.gitlab_private_token | ||
| 32 | + | ||
| 33 | + user = nil | ||
| 34 | + | ||
| 35 | + #Find user by email | ||
| 36 | + begin | ||
| 37 | + user = Gitlab.users(:search => email) | ||
| 38 | + rescue Gitlab::Error::NotFound, Gitlab::Error::Parsing | ||
| 39 | + user = nil | ||
| 40 | + end | ||
| 41 | + | ||
| 42 | + #User not found, create user | ||
| 43 | + if user == nil || user.count == 0 | ||
| 44 | + user = self.admins.first | ||
| 45 | + gitlab_user = Gitlab.create_user(user.email, '123456', {:username => user.identifier, :name => user.name, :provider => 'ldap'}) | ||
| 46 | + end | ||
| 47 | + | ||
| 48 | + if gitlab_user.nil? | ||
| 49 | + self.gitlab[:errors] = _('Gitlab user could not be created') | ||
| 50 | + return nil | ||
| 51 | + end | ||
| 52 | + | ||
| 53 | + #Create project for user | ||
| 54 | + begin | ||
| 55 | + #FIXME Why this? | ||
| 56 | + if gitlab_user.is_a?(Array) | ||
| 57 | + gitlab_user = user[0] | ||
| 58 | + end | ||
| 59 | + | ||
| 60 | + project_options = {} | ||
| 61 | + project_options[:user_id] = gitlab_user.id | ||
| 62 | + project_options[:issues_enabled ] = true | ||
| 63 | + project_options[:wall_enabled] = true | ||
| 64 | + project_options[:wiki_enabled] = true | ||
| 65 | + project_options[:public] = true | ||
| 66 | + project = Gitlab.create_project(self.identifier, project_options) | ||
| 67 | + | ||
| 68 | + #Create Web Hook for Jenkins' integration | ||
| 69 | +# Gitlab.add_project_hook(project.id, "#{self.jenkins[:url]}/gitlab/build_now") | ||
| 70 | +# createJenkinsJob(project.name, project.path_with_namespace, project.web_url, project.http_url_to_repo) | ||
| 71 | + | ||
| 72 | + rescue Gitlab::Error::NotFound, Gitlab::Error::Parsing | ||
| 73 | + #Project already exists | ||
| 74 | + end | ||
| 75 | + | ||
| 76 | + self.gitlab[:errors] = nil | ||
| 77 | + end | ||
| 78 | + | ||
| 79 | + # set an API endpoint | ||
| 80 | + def gitlab_host | ||
| 81 | + self.serpro_integration_plugin[:gitlab_host] | ||
| 82 | + end | ||
| 83 | + | ||
| 84 | + # set a user private token | ||
| 85 | + def gitlab_private_token | ||
| 86 | + self.serpro_integration_plugin[:gitlab_private_token] | ||
| 87 | + end | ||
| 88 | + | ||
| 89 | + ########################################## | ||
| 90 | + # Sonar stuff # | ||
| 91 | + ########################################## | ||
| 92 | + | ||
| 93 | +# after_create :create_sonar_project | ||
| 94 | + | ||
| 95 | + def sonar= params | ||
| 96 | + self.serpro_integration_plugin[:sonar] = params | ||
| 97 | + end | ||
| 98 | + | ||
| 99 | + def sonar | ||
| 100 | + self.serpro_integration_plugin[:sonar] ||= {} | ||
| 101 | + self.serpro_integration_plugin[:sonar] | ||
| 102 | + end | ||
| 103 | + | ||
| 104 | + ########################################## | ||
| 105 | + # Jenkins stuff # | ||
| 106 | + ########################################## | ||
| 107 | + | ||
| 108 | +# after_create :create_jenkis_project | ||
| 109 | + | ||
| 110 | + def jenkins= params | ||
| 111 | + self.serpro_integration_plugin[:jenkins] = params | ||
| 112 | + end | ||
| 113 | + | ||
| 114 | + def jenkins | ||
| 115 | + self.serpro_integration_plugin[:jenkins] ||= {} | ||
| 116 | + url = "#{self.serpro_integration_plugin[:jenkins][:host]}:" | ||
| 117 | + url += "#{self.serpro_integration_plugin[:jenkins][:port]}/" | ||
| 118 | + url += "#{self.serpro_integration_plugin[:jenkins][:context_name]}" | ||
| 119 | + self.serpro_integration_plugin[:jenkins][:url] = url | ||
| 120 | + self.serpro_integration_plugin[:jenkins] | ||
| 121 | + end | ||
| 122 | + | ||
| 123 | + | ||
| 124 | + #FIXME make jenkins integration works | ||
| 125 | + def create_jenkis_project | ||
| 126 | +#(projectName, repositoryPath, webUrl, gitUrl) | ||
| 127 | + | ||
| 128 | + @client = JenkinsApi::Client.new(:server_url => "#{$jenkins_url}/", | ||
| 129 | + :password => $jenkins_private_token, | ||
| 130 | + :username => $jenkins_user) | ||
| 131 | + | ||
| 132 | + xmlJenkins = " | ||
| 133 | + <maven2-moduleset plugin='maven-plugin@1.509'> | ||
| 134 | + <actions/> | ||
| 135 | + <description>Projeto criado para o repositório #{repositoryPath} do Gitlab - #{webUrl}</description> | ||
| 136 | + <logRotator class='hudson.tasks.LogRotator'> | ||
| 137 | + <daysToKeep>-1</daysToKeep> | ||
| 138 | + <numToKeep>2</numToKeep> | ||
| 139 | + <artifactDaysToKeep>-1</artifactDaysToKeep> | ||
| 140 | + <artifactNumToKeep>-1</artifactNumToKeep> | ||
| 141 | + </logRotator> | ||
| 142 | + <keepDependencies>false</keepDependencies> | ||
| 143 | + <properties/> | ||
| 144 | + <scm class='hudson.plugins.git.GitSCM' plugin='git@2.2.1'> | ||
| 145 | + <configVersion>2</configVersion> | ||
| 146 | + <userRemoteConfigs> | ||
| 147 | + <hudson.plugins.git.UserRemoteConfig> | ||
| 148 | + <url>#{gitUrl}</url> | ||
| 149 | + </hudson.plugins.git.UserRemoteConfig> | ||
| 150 | + </userRemoteConfigs> | ||
| 151 | + <branches> | ||
| 152 | + <hudson.plugins.git.BranchSpec> | ||
| 153 | + <name>*/master</name> | ||
| 154 | + </hudson.plugins.git.BranchSpec> | ||
| 155 | + </branches> | ||
| 156 | + <doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations> | ||
| 157 | + <submoduleCfg class='list'/> | ||
| 158 | + <extensions/> | ||
| 159 | + </scm> | ||
| 160 | + <canRoam>true</canRoam> | ||
| 161 | + <disabled>false</disabled> | ||
| 162 | + <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding> | ||
| 163 | + <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding> | ||
| 164 | + <jdk>(Inherit From Job)</jdk> | ||
| 165 | + <triggers class='vector'/> | ||
| 166 | + <concurrentBuild>false</concurrentBuild> | ||
| 167 | + <goals>clean package install deploy</goals> | ||
| 168 | + <aggregatorStyleBuild>true</aggregatorStyleBuild> | ||
| 169 | + <incrementalBuild>false</incrementalBuild> | ||
| 170 | + <perModuleEmail>true</perModuleEmail> | ||
| 171 | + <ignoreUpstremChanges>false</ignoreUpstremChanges> | ||
| 172 | + <archivingDisabled>false</archivingDisabled> | ||
| 173 | + <resolveDependencies>false</resolveDependencies> | ||
| 174 | + <processPlugins>false</processPlugins> | ||
| 175 | + <mavenValidationLevel>-1</mavenValidationLevel> | ||
| 176 | + <runHeadless>false</runHeadless> | ||
| 177 | + <disableTriggerDownstreamProjects>false</disableTriggerDownstreamProjects> | ||
| 178 | + <settings class='jenkins.mvn.DefaultSettingsProvider'/> | ||
| 179 | + <globalSettings class='jenkins.mvn.DefaultGlobalSettingsProvider'/> | ||
| 180 | + <reporters> | ||
| 181 | + <hudson.maven.reporters.MavenMailer> | ||
| 182 | + <recipients/> | ||
| 183 | + <dontNotifyEveryUnstableBuild>false</dontNotifyEveryUnstableBuild> | ||
| 184 | + <sendToIndividuals>true</sendToIndividuals> | ||
| 185 | + <perModuleEmail>true</perModuleEmail> | ||
| 186 | + </hudson.maven.reporters.MavenMailer> | ||
| 187 | + </reporters> | ||
| 188 | + <publishers> | ||
| 189 | + <hudson.plugins.sonar.SonarPublisher plugin='sonar@2.1'> | ||
| 190 | + <jdk>(Inherit From Job)</jdk> | ||
| 191 | + <branch/> | ||
| 192 | + <language/> | ||
| 193 | + <mavenOpts/> | ||
| 194 | + <jobAdditionalProperties/> | ||
| 195 | + <settings class='jenkins.mvn.DefaultSettingsProvider'/> | ||
| 196 | + <globalSettings class='jenkins.mvn.DefaultGlobalSettingsProvider'/> | ||
| 197 | + <usePrivateRepository>false</usePrivateRepository> | ||
| 198 | + </hudson.plugins.sonar.SonarPublisher> | ||
| 199 | + </publishers> | ||
| 200 | + <buildWrappers/> | ||
| 201 | + <prebuilders/> | ||
| 202 | + <postbuilders/> | ||
| 203 | + <runPostStepsIfResult> | ||
| 204 | + <name>FAILURE</name> | ||
| 205 | + <ordinal>2</ordinal> | ||
| 206 | + <color>RED</color> | ||
| 207 | + </runPostStepsIfResult> | ||
| 208 | + </maven2-moduleset> | ||
| 209 | + " | ||
| 210 | + | ||
| 211 | + begin | ||
| 212 | + @client.job.create(projectName, xmlJenkins) | ||
| 213 | + rescue JenkinsApi::Exceptions::ApiException | ||
| 214 | + | ||
| 215 | + end | ||
| 216 | + | ||
| 217 | + end | ||
| 218 | + | ||
| 219 | + | ||
| 220 | +end |
| @@ -0,0 +1,9 @@ | @@ -0,0 +1,9 @@ | ||
| 1 | +require_dependency 'profile' | ||
| 2 | + | ||
| 3 | +class Profile | ||
| 4 | + settings_items :allow_sonar_integration, :type => :boolean, :default => true | ||
| 5 | + settings_items :allow_gitlab_integration, :type => :boolean, :default => true | ||
| 6 | + | ||
| 7 | + #FIXME make test for default option | ||
| 8 | + settings_items :serpro_integration_plugin, :type => Hash, :default => {} | ||
| 9 | +end |
plugins/serpro_integration/lib/serpro_integration_plugin.rb
0 → 100644
| @@ -0,0 +1,64 @@ | @@ -0,0 +1,64 @@ | ||
| 1 | +class SerproIntegrationPlugin < Noosfero::Plugin | ||
| 2 | + | ||
| 3 | +#include ActionController::UrlWriter | ||
| 4 | +# include ActionView::Helpers::TagHelper | ||
| 5 | +# include ActionView::Helpers::FormTagHelper | ||
| 6 | +# include FormsHelper | ||
| 7 | + | ||
| 8 | + | ||
| 9 | +# include ActionView::Helpers | ||
| 10 | +# include FormsHelper | ||
| 11 | + | ||
| 12 | + def self.plugin_name | ||
| 13 | + "Serpro Integration Plugin" | ||
| 14 | + end | ||
| 15 | + | ||
| 16 | + def self.plugin_description | ||
| 17 | + _("Make integration with serpro servers.") | ||
| 18 | + end | ||
| 19 | + | ||
| 20 | +# def filter_comment(c) | ||
| 21 | +# c.reject! unless logged_in? || allowed_by_profile | ||
| 22 | +# end | ||
| 23 | + | ||
| 24 | + #FIXME make this test | ||
| 25 | + # User could not have this block | ||
| 26 | + def self.extra_blocks | ||
| 27 | + { SonarPlugin::SonarWidgetBlock => {:type => [Community] }, | ||
| 28 | + SonarPlugin::SmileBlock => {:type => [Community] } | ||
| 29 | + } | ||
| 30 | + end | ||
| 31 | + | ||
| 32 | + #FIXME make this test | ||
| 33 | + def profile_editor_extras | ||
| 34 | + lambda do | ||
| 35 | + render :file => 'profile-editor-extras' | ||
| 36 | + end | ||
| 37 | + end | ||
| 38 | + | ||
| 39 | + def profile_id | ||
| 40 | + context.profile | ||
| 41 | + end | ||
| 42 | + | ||
| 43 | + def stylesheet? | ||
| 44 | + true | ||
| 45 | + end | ||
| 46 | + | ||
| 47 | +# FIXME make this test | ||
| 48 | + def js_files | ||
| 49 | + ['smile_face.js'] | ||
| 50 | + end | ||
| 51 | + | ||
| 52 | +# def body_beginning | ||
| 53 | +# "<meta name='profile.allow_unauthenticated_comments'/>" if allowed_by_profile | ||
| 54 | +# end | ||
| 55 | +# | ||
| 56 | +# protected | ||
| 57 | +# | ||
| 58 | +# delegate :logged_in?, :to => :context | ||
| 59 | +# | ||
| 60 | +# def allowed_by_profile | ||
| 61 | +# context.profile && context.profile.allow_unauthenticated_comments | ||
| 62 | +# end | ||
| 63 | + | ||
| 64 | +end |
plugins/serpro_integration/lib/serpro_integration_plugin/smile_block.rb
0 → 100644
| @@ -0,0 +1,100 @@ | @@ -0,0 +1,100 @@ | ||
| 1 | +require 'open-uri' | ||
| 2 | +require 'json' | ||
| 3 | + | ||
| 4 | +class SonarPlugin::SmileBlock < Block | ||
| 5 | + | ||
| 6 | + | ||
| 7 | + METRIC_SUCCESS_DENSITY = 'test_success_density' | ||
| 8 | + METRIC_LOC = 'ncloc' | ||
| 9 | + METRIC_UNCOVERED_LINE = 'uncovered_lines' | ||
| 10 | + METRIC_COVERAGE = 'coverage' | ||
| 11 | + | ||
| 12 | + #FIXME make this test | ||
| 13 | + settings_items :sonar_info, :type => Hash, :default => {} | ||
| 14 | + | ||
| 15 | + def self.description | ||
| 16 | + _('Sonar Smile') | ||
| 17 | + end | ||
| 18 | + | ||
| 19 | + def help | ||
| 20 | + _('This block adds a smile face that make tecnical debits visible with funny way.') | ||
| 21 | + end | ||
| 22 | + | ||
| 23 | + #FIXME make this test | ||
| 24 | + def sonar_host | ||
| 25 | + self.owner.sonar_plugin['host'] | ||
| 26 | + end | ||
| 27 | + | ||
| 28 | + #FIXME make this test | ||
| 29 | + def sonar_project | ||
| 30 | + self.owner.sonar_plugin['project'] #|| '' | ||
| 31 | + end | ||
| 32 | + | ||
| 33 | +#FIXME make this test | ||
| 34 | + def smile_factor | ||
| 35 | + collect_sonar_information | ||
| 36 | + factor = (self.sonar_info[METRIC_COVERAGE] * self.sonar_info[METRIC_SUCCESS_DENSITY]).to_f/1000 | ||
| 37 | + factor | ||
| 38 | + end | ||
| 39 | + | ||
| 40 | + #FIXME make this test | ||
| 41 | + def content(args={}) | ||
| 42 | + smile_face_id = 'smileFace-' + self.id.to_s | ||
| 43 | + | ||
| 44 | + content_tag(:div, | ||
| 45 | + content_tag(:canvas, '', :id => smile_face_id, :width => '95%', :height => '95%' ) + | ||
| 46 | + "<script type='text/javascript'>drawFace('#{smile_face_id}', '#{self.smile_factor}')</script>", | ||
| 47 | + :class => 'smile' | ||
| 48 | + ) | ||
| 49 | + end | ||
| 50 | + | ||
| 51 | + #FIXME make this test | ||
| 52 | + def self.metrics | ||
| 53 | + [ | ||
| 54 | + METRIC_SUCCESS_DENSITY, | ||
| 55 | + METRIC_LOC, | ||
| 56 | + METRIC_UNCOVERED_LINE, | ||
| 57 | + METRIC_COVERAGE | ||
| 58 | + ] | ||
| 59 | + end | ||
| 60 | + | ||
| 61 | + private | ||
| 62 | + | ||
| 63 | + #FIXME make this test | ||
| 64 | + def collect_sonar_information | ||
| 65 | + return false unless cache_expired? | ||
| 66 | + begin | ||
| 67 | + data = open("#{self.sonar_host}/api/resources?resource=#{self.sonar_project}&metrics=ncloc,coverage,weighted_violations,uncovered_lines,test_success_density&format=json").read | ||
| 68 | + self.sonar_info = parse_sonar_resource(JSON.parse(data).first) | ||
| 69 | + rescue | ||
| 70 | + self.sonar_info = {} | ||
| 71 | + end | ||
| 72 | + self.sonar_info[:updated_at] = Time.now | ||
| 73 | + self.save | ||
| 74 | + end | ||
| 75 | + | ||
| 76 | + #FIXME make this test | ||
| 77 | + def parse_sonar_resource(data) | ||
| 78 | + parsed_data = {} | ||
| 79 | + return {} if data['msr'].nil? | ||
| 80 | + data['msr'].map do |metric| | ||
| 81 | + self.class.metrics.map do |defined_metric| | ||
| 82 | + parsed_data[defined_metric] = metric['val'] if metric['key'] == defined_metric | ||
| 83 | + end | ||
| 84 | + end | ||
| 85 | + parsed_data | ||
| 86 | + end | ||
| 87 | + | ||
| 88 | + #FIXME make this test | ||
| 89 | + def cache_expired? | ||
| 90 | + return true if self.sonar_info[:updated_at].nil? | ||
| 91 | + (Time.now - self.sonar_info[:updated_at]) > cache_timestamp | ||
| 92 | + end | ||
| 93 | + | ||
| 94 | + #FIXME make this test | ||
| 95 | + # Cach time to load new data in seconds | ||
| 96 | + def cache_timestamp | ||
| 97 | + 60 * 60 | ||
| 98 | + end | ||
| 99 | + | ||
| 100 | +end |
plugins/serpro_integration/lib/serpro_integration_plugin/sonar_widget_block.rb
0 → 100644
| @@ -0,0 +1,81 @@ | @@ -0,0 +1,81 @@ | ||
| 1 | +class SerproIntegrationrPlugin::SonarWidgetBlock < Block | ||
| 2 | + | ||
| 3 | + #FIXME make this test | ||
| 4 | + AVAILABLE_WIDGETS = { | ||
| 5 | + 'project_motion_chart' => 'Project Motion Chart', | ||
| 6 | + 'timeline' => 'Timeline', | ||
| 7 | + 'complexity' => 'Complexity' | ||
| 8 | + } | ||
| 9 | + | ||
| 10 | + #FIXME make this test. Make test for default widget | ||
| 11 | + settings_items :widget, :type => String, :default => 'timeline' | ||
| 12 | + | ||
| 13 | + def self.description | ||
| 14 | + _('Sonar Widgets') | ||
| 15 | + end | ||
| 16 | + | ||
| 17 | + def help | ||
| 18 | + _('This block adds sonar widgets on profile.') | ||
| 19 | + end | ||
| 20 | + | ||
| 21 | + #FIXME make this test | ||
| 22 | + def sonar_host | ||
| 23 | + self.owner.serpro_integration_plugin['host'] | ||
| 24 | + end | ||
| 25 | + | ||
| 26 | + #FIXME make this test | ||
| 27 | + def sonar_project | ||
| 28 | + self.owner.serpro_integration_plugin['project'] | ||
| 29 | + end | ||
| 30 | + | ||
| 31 | + #FIXME make this test | ||
| 32 | + def widget_url | ||
| 33 | + self.sonar_host + 'widget?id=' + self.widget + '&resource=' + self.sonar_project + '&metric1=complexity&metric2=ncloc' | ||
| 34 | + end | ||
| 35 | + | ||
| 36 | + #FIXME make this test | ||
| 37 | + def is_widget_well_formed_url? | ||
| 38 | + !self.widget_url.match(/http[s]?:\/\/[\w|.|\/]+\/widget\?id=[\w]+&resource=[\w|\W]+/).nil? | ||
| 39 | + end | ||
| 40 | + | ||
| 41 | + #FIXME make this test | ||
| 42 | + def widget_width | ||
| 43 | + case widget | ||
| 44 | + when 'project_motion_chart' | ||
| 45 | + '360px' | ||
| 46 | + when 'timeline' | ||
| 47 | + '100%' | ||
| 48 | + when 'complexity' | ||
| 49 | + '100%' | ||
| 50 | + else | ||
| 51 | + '300px' | ||
| 52 | + end | ||
| 53 | + end | ||
| 54 | + | ||
| 55 | + #FIXME make this test | ||
| 56 | + def widget_height | ||
| 57 | + case widget | ||
| 58 | + when 'project_motion_chart' | ||
| 59 | + '450px' | ||
| 60 | + when 'timeline' | ||
| 61 | + '205px' | ||
| 62 | + when 'complexity' | ||
| 63 | + '170px' | ||
| 64 | + else | ||
| 65 | + '300px' | ||
| 66 | + end | ||
| 67 | + end | ||
| 68 | + | ||
| 69 | + def content(args={}) | ||
| 70 | +# render this url | ||
| 71 | +#http://sonar.serpro/widget?id=timeline&resource=br.gov.fazenda.coaf.siscoaf:siscoaf-parent&metric1=complexity&metric2=ncloc | ||
| 72 | + | ||
| 73 | + block = self | ||
| 74 | + | ||
| 75 | + lambda do | ||
| 76 | + render :file => 'sonar_widget_block', :locals => { :block => block } | ||
| 77 | + end | ||
| 78 | + | ||
| 79 | + end | ||
| 80 | + | ||
| 81 | +end |
| @@ -0,0 +1,129 @@ | @@ -0,0 +1,129 @@ | ||
| 1 | +function drawBaseFace(element_id) { | ||
| 2 | + var canvas = document.getElementById(element_id); | ||
| 3 | + var ctx = canvas.getContext("2d"); | ||
| 4 | + | ||
| 5 | + var x = canvas.width / 2; | ||
| 6 | + var y = canvas.height / 2; | ||
| 7 | + var radius = canvas.width/2 - 1; | ||
| 8 | + var startAngle = 0; | ||
| 9 | + var endAngle = 2 * Math.PI; | ||
| 10 | + | ||
| 11 | + ctx.beginPath(); | ||
| 12 | + ctx.arc(x, y, radius, startAngle, endAngle); | ||
| 13 | + ctx.stroke(); | ||
| 14 | + ctx.fillStyle = "yellow"; | ||
| 15 | + ctx.fill(); | ||
| 16 | +} | ||
| 17 | + | ||
| 18 | +function drawSmile(element_id, factor){ | ||
| 19 | + var canvas = document.getElementById(element_id); | ||
| 20 | + var ctx = canvas.getContext("2d"); | ||
| 21 | + var x = canvas.width / 2; | ||
| 22 | + var y = canvas.height / 2 | ||
| 23 | + var radius = canvas.width/2 - canvas.width/4; | ||
| 24 | + | ||
| 25 | + var startAngle = 0; | ||
| 26 | + var endAngle = 0; | ||
| 27 | + var delta = 0; | ||
| 28 | + | ||
| 29 | + ctx.beginPath(); | ||
| 30 | + ctx.lineWidth = canvas.width/100 * 2; | ||
| 31 | + | ||
| 32 | + if (factor >= 0 && factor < 5){ | ||
| 33 | + //Draw sadness mouth | ||
| 34 | + delta = 0.5 - factor* 0.1 | ||
| 35 | + startAngle = (1.5 - delta) * Math.PI; | ||
| 36 | + endAngle = (1.5 + delta) * Math.PI; | ||
| 37 | + radius = radius - radius*delta; | ||
| 38 | + y = y + (radius + radius*(1 - delta)); | ||
| 39 | + ctx.arc(x, y, radius, startAngle, endAngle); | ||
| 40 | + } else if (factor == 5) { | ||
| 41 | + //Draw normal mouth | ||
| 42 | + ctx.moveTo(x-canvas.width/8,y+canvas.width/8); | ||
| 43 | + ctx.lineTo(x-canvas.width/8+(canvas.width/4),y+canvas.width/8); | ||
| 44 | + } else if (factor > 5 && factor <= 10) { | ||
| 45 | + //Draw happiness mouth | ||
| 46 | + delta = 1 - factor * 0.1 | ||
| 47 | + startAngle = delta * Math.PI; | ||
| 48 | + endAngle = (1 - delta) * Math.PI; | ||
| 49 | + radius = radius - radius*delta; | ||
| 50 | + y = y - (radius - radius*(1-delta)); | ||
| 51 | + ctx.arc(x, y, radius, startAngle, endAngle); | ||
| 52 | + }else{ | ||
| 53 | + //Draw scare mouth | ||
| 54 | + radius = radius*0.4 | ||
| 55 | + y = y + radius; | ||
| 56 | + ctx.ellipse(x,y,radius*0.4, radius,0,0,2 * Math.PI, false); | ||
| 57 | + ctx.fill(); | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + | ||
| 61 | + // line color | ||
| 62 | + ctx.strokeStyle = 'black'; | ||
| 63 | + ctx.stroke(); | ||
| 64 | +} | ||
| 65 | + | ||
| 66 | +function drawEyes(element_id){ | ||
| 67 | + var canvas = document.getElementById(element_id); | ||
| 68 | + var ctx = canvas.getContext("2d"); | ||
| 69 | + var centerX = canvas.width/5; | ||
| 70 | + var centerY = 0; | ||
| 71 | + var radius = canvas.width * 0.05; | ||
| 72 | + | ||
| 73 | + // save state | ||
| 74 | + ctx.save(); | ||
| 75 | + | ||
| 76 | + // translate context so height is 1/3'rd from top of enclosing circle | ||
| 77 | + ctx.translate(canvas.width / 2, canvas.height / 3); | ||
| 78 | + | ||
| 79 | + // scale context horizontally by 50% | ||
| 80 | + ctx.scale(.5, 1); | ||
| 81 | + | ||
| 82 | + // draw circle which will be stretched into an oval | ||
| 83 | + ctx.beginPath(); | ||
| 84 | + ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); | ||
| 85 | + | ||
| 86 | + // restore to original state | ||
| 87 | + ctx.restore(); | ||
| 88 | + | ||
| 89 | + // apply styling | ||
| 90 | + ctx.fillStyle = 'black'; | ||
| 91 | + ctx.fill(); | ||
| 92 | + ctx.lineWidth = 2; | ||
| 93 | + ctx.strokeStyle = 'black'; | ||
| 94 | + ctx.stroke(); | ||
| 95 | + | ||
| 96 | + | ||
| 97 | + //left eye | ||
| 98 | + centerX = centerX * -1; | ||
| 99 | + | ||
| 100 | + // save state | ||
| 101 | + ctx.save(); | ||
| 102 | + | ||
| 103 | + // translate context so height is 1/3'rd from top of enclosing circle | ||
| 104 | + ctx.translate(canvas.width / 2, canvas.height / 3); | ||
| 105 | + | ||
| 106 | + // scale context horizontally by 50% | ||
| 107 | + ctx.scale(.5, 1); | ||
| 108 | + | ||
| 109 | + // draw circle which will be stretched into an oval | ||
| 110 | + ctx.beginPath(); | ||
| 111 | + ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); | ||
| 112 | + | ||
| 113 | + // restore to original state | ||
| 114 | + ctx.restore(); | ||
| 115 | + | ||
| 116 | + // apply styling | ||
| 117 | + ctx.fillStyle = 'black'; | ||
| 118 | + ctx.fill(); | ||
| 119 | + ctx.lineWidth = 2; | ||
| 120 | + ctx.strokeStyle = 'black'; | ||
| 121 | + ctx.stroke(); | ||
| 122 | +} | ||
| 123 | + | ||
| 124 | + | ||
| 125 | +function drawFace(element_id, factor){ | ||
| 126 | + drawBaseFace(element_id); | ||
| 127 | + drawEyes(element_id); | ||
| 128 | + drawSmile(element_id, factor); | ||
| 129 | +} |
| @@ -0,0 +1,142 @@ | @@ -0,0 +1,142 @@ | ||
| 1 | +<html> | ||
| 2 | + <head> </head> | ||
| 3 | + <body> | ||
| 4 | + <canvas id="smileFace" width="60" height="60"></canvas> | ||
| 5 | +<script> | ||
| 6 | + | ||
| 7 | +function drawBaseFace() { | ||
| 8 | + var canvas = document.getElementById("smileFace"); | ||
| 9 | + var ctx = canvas.getContext("2d"); | ||
| 10 | + | ||
| 11 | + var x = canvas.width / 2; | ||
| 12 | + var y = canvas.height / 2; | ||
| 13 | + var radius = canvas.width/2 - 1; | ||
| 14 | + var startAngle = 0; | ||
| 15 | + var endAngle = 2 * Math.PI; | ||
| 16 | + | ||
| 17 | + ctx.beginPath(); | ||
| 18 | + ctx.arc(x, y, radius, startAngle, endAngle); | ||
| 19 | + ctx.stroke(); | ||
| 20 | + ctx.fillStyle = "yellow"; | ||
| 21 | + ctx.fill(); | ||
| 22 | +} | ||
| 23 | + | ||
| 24 | +function drawSmile(factor){ | ||
| 25 | + var canvas = document.getElementById("smileFace"); | ||
| 26 | + var ctx = canvas.getContext("2d"); | ||
| 27 | + var x = canvas.width / 2; | ||
| 28 | + var y = canvas.height / 2 | ||
| 29 | + var radius = canvas.width/2 - canvas.width/4; | ||
| 30 | + | ||
| 31 | + var startAngle = 0; | ||
| 32 | + var endAngle = 0; | ||
| 33 | + var delta = 0; | ||
| 34 | + | ||
| 35 | + ctx.beginPath(); | ||
| 36 | + ctx.lineWidth = canvas.width/100 * 2; | ||
| 37 | + | ||
| 38 | + if (factor >= 0 && factor < 5){ | ||
| 39 | + //Draw sadness mouth | ||
| 40 | + delta = 0.5 - factor* 0.1 | ||
| 41 | + startAngle = (1.5 - delta) * Math.PI; | ||
| 42 | + endAngle = (1.5 + delta) * Math.PI; | ||
| 43 | + radius = radius - radius*delta; | ||
| 44 | + y = y + (radius + radius*(1 - delta)); | ||
| 45 | + ctx.arc(x, y, radius, startAngle, endAngle); | ||
| 46 | + } else if (factor == 5) { | ||
| 47 | + //Draw normal mouth | ||
| 48 | + ctx.moveTo(x-canvas.width/8,y+canvas.width/8); | ||
| 49 | + ctx.lineTo(x-canvas.width/8+(canvas.width/4),y+canvas.width/8); | ||
| 50 | + } else if (factor > 5 && factor <= 10) { | ||
| 51 | + //Draw happiness mouth | ||
| 52 | + delta = 1 - factor * 0.1 | ||
| 53 | + startAngle = delta * Math.PI; | ||
| 54 | + endAngle = (1 - delta) * Math.PI; | ||
| 55 | + radius = radius - radius*delta; | ||
| 56 | + y = y - (radius - radius*(1-delta)); | ||
| 57 | + ctx.arc(x, y, radius, startAngle, endAngle); | ||
| 58 | + }else{ | ||
| 59 | + //Draw scare mouth | ||
| 60 | + radius = radius*0.4 | ||
| 61 | + y = y + radius; | ||
| 62 | + ctx.ellipse(x,y,radius*0.4, radius,0,0,2 * Math.PI, false); | ||
| 63 | + ctx.fill(); | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + | ||
| 67 | + // line color | ||
| 68 | + ctx.strokeStyle = 'black'; | ||
| 69 | + ctx.stroke(); | ||
| 70 | +} | ||
| 71 | + | ||
| 72 | +function drawEyes(){ | ||
| 73 | + var canvas = document.getElementById("smileFace"); | ||
| 74 | + var ctx = canvas.getContext("2d"); | ||
| 75 | + var centerX = canvas.width/5; | ||
| 76 | + var centerY = 0; | ||
| 77 | + var radius = canvas.width * 0.05; | ||
| 78 | + | ||
| 79 | + // save state | ||
| 80 | + ctx.save(); | ||
| 81 | + | ||
| 82 | + // translate context so height is 1/3'rd from top of enclosing circle | ||
| 83 | + ctx.translate(canvas.width / 2, canvas.height / 3); | ||
| 84 | + | ||
| 85 | + // scale context horizontally by 50% | ||
| 86 | + ctx.scale(.5, 1); | ||
| 87 | + | ||
| 88 | + // draw circle which will be stretched into an oval | ||
| 89 | + ctx.beginPath(); | ||
| 90 | + ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); | ||
| 91 | + | ||
| 92 | + // restore to original state | ||
| 93 | + ctx.restore(); | ||
| 94 | + | ||
| 95 | + // apply styling | ||
| 96 | + ctx.fillStyle = 'black'; | ||
| 97 | + ctx.fill(); | ||
| 98 | + ctx.lineWidth = 2; | ||
| 99 | + ctx.strokeStyle = 'black'; | ||
| 100 | + ctx.stroke(); | ||
| 101 | + | ||
| 102 | + | ||
| 103 | + //left eye | ||
| 104 | + centerX = centerX * -1; | ||
| 105 | + | ||
| 106 | + // save state | ||
| 107 | + ctx.save(); | ||
| 108 | + | ||
| 109 | + // translate context so height is 1/3'rd from top of enclosing circle | ||
| 110 | + ctx.translate(canvas.width / 2, canvas.height / 3); | ||
| 111 | + | ||
| 112 | + // scale context horizontally by 50% | ||
| 113 | + ctx.scale(.5, 1); | ||
| 114 | + | ||
| 115 | + // draw circle which will be stretched into an oval | ||
| 116 | + ctx.beginPath(); | ||
| 117 | + ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); | ||
| 118 | + | ||
| 119 | + // restore to original state | ||
| 120 | + ctx.restore(); | ||
| 121 | + | ||
| 122 | + // apply styling | ||
| 123 | + ctx.fillStyle = 'black'; | ||
| 124 | + ctx.fill(); | ||
| 125 | + ctx.lineWidth = 2; | ||
| 126 | + ctx.strokeStyle = 'black'; | ||
| 127 | + ctx.stroke(); | ||
| 128 | +} | ||
| 129 | + | ||
| 130 | + | ||
| 131 | +function drawFace(factor){ | ||
| 132 | + drawBaseFace(); | ||
| 133 | + drawEyes(); | ||
| 134 | + drawSmile(factor); | ||
| 135 | +} | ||
| 136 | + | ||
| 137 | +drawFace(9); | ||
| 138 | + | ||
| 139 | +</script> | ||
| 140 | + | ||
| 141 | + </body> | ||
| 142 | +</html> |
plugins/serpro_integration/test/unit/sonar_plugin_test.rb
0 → 100644
| @@ -0,0 +1,41 @@ | @@ -0,0 +1,41 @@ | ||
| 1 | +require File.dirname(__FILE__) + '/../../../../test/test_helper' | ||
| 2 | + | ||
| 3 | +class RequireAuthToCommentPluginTest < ActiveSupport::TestCase | ||
| 4 | + | ||
| 5 | + def setup | ||
| 6 | + @plugin = RequireAuthToCommentPlugin.new | ||
| 7 | + @comment = Comment.new | ||
| 8 | + end | ||
| 9 | + | ||
| 10 | + attr_reader :plugin, :comment | ||
| 11 | + | ||
| 12 | + should 'reject comments for unauthenticated users' do | ||
| 13 | + plugin.context = logged_in(false) | ||
| 14 | + plugin.filter_comment(comment) | ||
| 15 | + assert comment.rejected? | ||
| 16 | + end | ||
| 17 | + | ||
| 18 | + should 'allow comments from authenticated users' do | ||
| 19 | + plugin.context = logged_in(true) | ||
| 20 | + plugin.filter_comment(comment) | ||
| 21 | + assert !comment.rejected? | ||
| 22 | + end | ||
| 23 | + | ||
| 24 | + should 'allow comments from unauthenticated users if allowed by profile' do | ||
| 25 | + plugin.context = logged_in(false) | ||
| 26 | + plugin.context.profile.allow_unauthenticated_comments = true | ||
| 27 | + | ||
| 28 | + plugin.filter_comment(comment) | ||
| 29 | + assert !comment.rejected? | ||
| 30 | + end | ||
| 31 | + | ||
| 32 | + protected | ||
| 33 | + | ||
| 34 | + def logged_in(boolean) | ||
| 35 | + controller = mock() | ||
| 36 | + controller.stubs(:logged_in?).returns(boolean) | ||
| 37 | + controller.stubs(:profile).returns(Profile.new) | ||
| 38 | + controller | ||
| 39 | + end | ||
| 40 | + | ||
| 41 | +end |
plugins/serpro_integration/views/profile-editor-extras.html.erb
0 → 100644
| @@ -0,0 +1,49 @@ | @@ -0,0 +1,49 @@ | ||
| 1 | + | ||
| 2 | +<div id='serpro-integration'> | ||
| 3 | + <div id='gitlab' class='gitlab'> | ||
| 4 | + <%= render :partial => 'gitlab' %> | ||
| 5 | + </div> | ||
| 6 | + | ||
| 7 | + <div> | ||
| 8 | + <%= labelled_check_box(_('Uses sonar integration'), 'profile_data[allow_sonar_integration]', true, profile.allow_sonar_integration) %> | ||
| 9 | + </div> | ||
| 10 | + | ||
| 11 | + <ul class='sonar'> | ||
| 12 | + <h2><%= _('Sonar Integration') %></h2> | ||
| 13 | + <li> | ||
| 14 | + <%= labelled_text_field(_('Server Host'), 'profile_data[sonar]host]', profile.sonar[:host]) %> | ||
| 15 | + </li> | ||
| 16 | + <li> | ||
| 17 | + <%= labelled_text_field(_('Project: '), 'profile_data[sonar][project]', profile.sonar[:project]) %> | ||
| 18 | + </li> | ||
| 19 | + </ul> | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + <div> | ||
| 23 | + <%= labelled_check_box(_('Uses Jenkins integration'), 'profile_data[allow_jenkins_integration]', true, profile.allow_jenkins_integration) %> | ||
| 24 | + </div> | ||
| 25 | + | ||
| 26 | + <ul class='jenkins'> | ||
| 27 | + <h2><%= _('Jenkins Integration') %></h2> | ||
| 28 | + <li> | ||
| 29 | + <%= labelled_text_field(_('Server Host'), 'profile_data[jenkins][host]', profile.jenkins[:host]) %> | ||
| 30 | + </li> | ||
| 31 | + <li> | ||
| 32 | + <%= labelled_text_field(_('Server Port'), 'profile_data[jenkins][port]', profile.jenkins[:port]) %> | ||
| 33 | + </li> | ||
| 34 | + <li> | ||
| 35 | + <%= labelled_text_field(_('Server Context Name'), 'profile_data[jenkins][context_name]', profile.jenkins[:context_name]) %> | ||
| 36 | + </li> | ||
| 37 | + <li> | ||
| 38 | + <%= labelled_text_field(_('Server User'), 'profile_data[jenkins][user]', profile.jenkins[:user]) %> | ||
| 39 | + </li> | ||
| 40 | + <li> | ||
| 41 | + <%= labelled_text_field(_('Server Private Token'), 'profile_data[jenkins][private_token]', profile.jenkins[:private_token]) %> | ||
| 42 | + </li> | ||
| 43 | + <li> | ||
| 44 | + <%= labelled_text_field(_('Server Url'), 'profile_data[jenkins][url]', profile.jenkins[:url], {:disabled => true}) %> | ||
| 45 | + </li> | ||
| 46 | + | ||
| 47 | + </ul> | ||
| 48 | + | ||
| 49 | +</div> |
plugins/serpro_integration/views/profile_design/sonar_plugin/_sonar_widget_block.rhtml
0 → 100644
plugins/serpro_integration/views/profile_editor/_gitlab.html.erb
0 → 100644
| @@ -0,0 +1,22 @@ | @@ -0,0 +1,22 @@ | ||
| 1 | +<div class='option'> | ||
| 2 | + <%= labelled_check_box(_('Uses Gitlab integration'), 'profile_data[allow_gitlab_integration]', true, profile.allow_gitlab_integration) %> | ||
| 3 | +</div> | ||
| 4 | + | ||
| 5 | +<ul> | ||
| 6 | + <h2> | ||
| 7 | + <%= _('Gitlab Integration') %> | ||
| 8 | + <%= link_to_remote _('Force'), :url => {:controller => 'serpro_integration_plugin_myprofile', :action => 'create_gitlab'} %> | ||
| 9 | + | ||
| 10 | + </h2> | ||
| 11 | + <li> | ||
| 12 | + <%= labelled_text_field(_('Server Host'), 'profile_data[gitlab][host]', profile.gitlab[:host]) %> | ||
| 13 | + </li> | ||
| 14 | + <li> | ||
| 15 | + <%= labelled_text_field(_('User private token: '), 'profile_data[gitlab][private_token]', profile.gitlab[:private_token]) %> | ||
| 16 | + </li> | ||
| 17 | + <li> | ||
| 18 | + <%= _('Erros: %s') % (profile.gitlab[:errors] || _('None')) %> | ||
| 19 | + </li> | ||
| 20 | + | ||
| 21 | +</ul> | ||
| 22 | + |
plugins/serpro_integration/views/sonar_widget_block.rhtml
0 → 100644
| @@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
| 1 | +<div class='widget'> | ||
| 2 | + <% if block.is_widget_well_formed_url? %> | ||
| 3 | + <iframe width='<%=block.widget_width%>' height='<%=block.widget_height%>' src='<%=block.widget_url%>' frameborder="0" allowfullscreen></iframe> | ||
| 4 | + <% else %> | ||
| 5 | + <div class='wrong'> | ||
| 6 | + <iframe width='<%=block.widget_width%>' height='<%=block.widget_height%>' src='<%=block.widget_url%>' frameborder="0" allowfullscreen></iframe> | ||
| 7 | + <%= _('Something wrong happened. Please see your sonar configuration.') %> | ||
| 8 | + </div> | ||
| 9 | + <% end %> | ||
| 10 | +</div> |
test/fixtures/files/500.html
| @@ -0,0 +1,151 @@ | @@ -0,0 +1,151 @@ | ||
| 1 | +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | ||
| 2 | +<html xmlns="http://www.w3.org/1999/xhtml" > | ||
| 3 | + <head> | ||
| 4 | + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> | ||
| 5 | + <meta http-equiv="refresh" content="60"/> | ||
| 6 | + <title>Technical problems</title> | ||
| 7 | + <link rel="stylesheet" type="text/css" href="/designs/themes/default/errors.css"/> | ||
| 8 | + <link rel="shortcut icon" href='/designs/themes/default/favicon.ico' type="image/x-icon" /> | ||
| 9 | + <script type='text/javascript' src='/javascripts/prototype.js'></script> | ||
| 10 | + <script type='text/javascript' src='/javascripts/errors.js'></script> | ||
| 11 | +</head> | ||
| 12 | +<body onload='display_error_message()'> | ||
| 13 | + <div id='wrap'> | ||
| 14 | + <div id='header'> | ||
| 15 | + <div id='logo'> | ||
| 16 | + | ||
| 17 | + </div> | ||
| 18 | + </div> | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + <div id='de' style='display: none' class='message'> | ||
| 22 | + <h1>Kurzzeitiges Systemproblem</h1> | ||
| 23 | + <p> | ||
| 24 | + Unser technisches Team arbeitet gerade daran, bitte probieren Sie es nachher erneut. Wir entschuldigen uns für die Unannehmlichkeiten. | ||
| 25 | + </p> | ||
| 26 | + <ul> | ||
| 27 | + <li><a href='javascript: history.back()'>Zurück</a></li> | ||
| 28 | + <li><a href='/'>Gehe zur Homepage</a></li> | ||
| 29 | + </ul> | ||
| 30 | + </div> | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + <div id='en' style='display: none' class='message'> | ||
| 34 | + <h1>Temporary system problem</h1> | ||
| 35 | + <p> | ||
| 36 | + Our technical team is working on it, please try again later. Sorry for the inconvenience. | ||
| 37 | + </p> | ||
| 38 | + <ul> | ||
| 39 | + <li><a href='javascript: history.back()'>Go back</a></li> | ||
| 40 | + <li><a href='/'>Go to the site home page</a></li> | ||
| 41 | + </ul> | ||
| 42 | + </div> | ||
| 43 | + | ||
| 44 | + | ||
| 45 | + <div id='eo' style='display: none' class='message'> | ||
| 46 | + <h1>Temporary system problem</h1> | ||
| 47 | + <p> | ||
| 48 | + Our technical team is working on it, please try again later. Sorry for the inconvenience. | ||
| 49 | + </p> | ||
| 50 | + <ul> | ||
| 51 | + <li><a href='javascript: history.back()'>Go back</a></li> | ||
| 52 | + <li><a href='/'>Go to the site home page</a></li> | ||
| 53 | + </ul> | ||
| 54 | + </div> | ||
| 55 | + | ||
| 56 | + | ||
| 57 | + <div id='es' style='display: none' class='message'> | ||
| 58 | + <h1>Problema temporal del sistema</h1> | ||
| 59 | + <p> | ||
| 60 | + Nuestro equipo técnico está trabajando en ello, por favor, inténtalo de nuevo más tarde. Disculpa las molestias. | ||
| 61 | + </p> | ||
| 62 | + <ul> | ||
| 63 | + <li><a href='javascript: history.back()'>Regresar</a></li> | ||
| 64 | + <li><a href='/'>Ir a la página de inicio del sitio</a></li> | ||
| 65 | + </ul> | ||
| 66 | + </div> | ||
| 67 | + | ||
| 68 | + | ||
| 69 | + <div id='fr' style='display: none' class='message'> | ||
| 70 | + <h1>Problème temporaire du système.</h1> | ||
| 71 | + <p> | ||
| 72 | + Notre équipe technique est en train d'y travailler. Merci de réessayer plus tard. Nous sommes désolés de la gêne occasionnée. | ||
| 73 | + </p> | ||
| 74 | + <ul> | ||
| 75 | + <li><a href='javascript: history.back()'>Retour</a></li> | ||
| 76 | + <li><a href='/'>Aller à la page d'accueil du site</a></li> | ||
| 77 | + </ul> | ||
| 78 | + </div> | ||
| 79 | + | ||
| 80 | + | ||
| 81 | + <div id='hy' style='display: none' class='message'> | ||
| 82 | + <h1>Temporary system problem</h1> | ||
| 83 | + <p> | ||
| 84 | + Our technical team is working on it, please try again later. Sorry for the inconvenience. | ||
| 85 | + </p> | ||
| 86 | + <ul> | ||
| 87 | + <li><a href='javascript: history.back()'>Վերադառնալ</a></li> | ||
| 88 | + <li><a href='/'>Go to the site home page</a></li> | ||
| 89 | + </ul> | ||
| 90 | + </div> | ||
| 91 | + | ||
| 92 | + | ||
| 93 | + <div id='it' style='display: none' class='message'> | ||
| 94 | + <h1>Temporary system problem</h1> | ||
| 95 | + <p> | ||
| 96 | + Our technical team is working on it, please try again later. Sorry for the inconvenience. | ||
| 97 | + </p> | ||
| 98 | + <ul> | ||
| 99 | + <li><a href='javascript: history.back()'>Go back</a></li> | ||
| 100 | + <li><a href='/'>Go to the site home page</a></li> | ||
| 101 | + </ul> | ||
| 102 | + </div> | ||
| 103 | + | ||
| 104 | + | ||
| 105 | + <div id='pt' style='display: none' class='message'> | ||
| 106 | + <h1>Problema temporário no sistema</h1> | ||
| 107 | + <p> | ||
| 108 | + Nossa equipe técnica está trabalhando nele, por favor tente mais tarde. Perdoe o incoveniente. | ||
| 109 | + </p> | ||
| 110 | + <ul> | ||
| 111 | + <li><a href='javascript: history.back()'>Voltar</a></li> | ||
| 112 | + <li><a href='/'>Ir para a página inicial do site.</a></li> | ||
| 113 | + </ul> | ||
| 114 | + </div> | ||
| 115 | + | ||
| 116 | + | ||
| 117 | + <div id='ru' style='display: none' class='message'> | ||
| 118 | + <h1>Временная ошибка системы</h1> | ||
| 119 | + <p> | ||
| 120 | + Техники уже работают над проблемой, пожалуйста, попробуйте позже. | ||
| 121 | + </p> | ||
| 122 | + <ul> | ||
| 123 | + <li><a href='javascript: history.back()'>Назад</a></li> | ||
| 124 | + <li><a href='/'>Перейти на домашнюю страницу сайта</a></li> | ||
| 125 | + </ul> | ||
| 126 | + </div> | ||
| 127 | + | ||
| 128 | + <div id='languages'> | ||
| 129 | + | ||
| 130 | + <a href="javascript: display_error_message('de')">Deutsch</a> | ||
| 131 | + | ||
| 132 | + <a href="javascript: display_error_message('en')">English</a> | ||
| 133 | + | ||
| 134 | + <a href="javascript: display_error_message('eo')">Esperanto</a> | ||
| 135 | + | ||
| 136 | + <a href="javascript: display_error_message('es')">Español</a> | ||
| 137 | + | ||
| 138 | + <a href="javascript: display_error_message('fr')">Français</a> | ||
| 139 | + | ||
| 140 | + <a href="javascript: display_error_message('hy')">հայերեն լեզու</a> | ||
| 141 | + | ||
| 142 | + <a href="javascript: display_error_message('it')">Italiano</a> | ||
| 143 | + | ||
| 144 | + <a href="javascript: display_error_message('pt')">Português</a> | ||
| 145 | + | ||
| 146 | + <a href="javascript: display_error_message('ru')">русский язык</a> | ||
| 147 | + | ||
| 148 | + </div> | ||
| 149 | + </div> | ||
| 150 | +</body> | ||
| 151 | +</html> |
test/functional/profile_controller_test.rb
| @@ -474,17 +474,23 @@ class ProfileControllerTest < ActionController::TestCase | @@ -474,17 +474,23 @@ class ProfileControllerTest < ActionController::TestCase | ||
| 474 | assert_equal "/profile/#{community.identifier}", @request.session[:previous_location] | 474 | assert_equal "/profile/#{community.identifier}", @request.session[:previous_location] |
| 475 | end | 475 | end |
| 476 | 476 | ||
| 477 | - should 'redirect to location before login after join community' do | 477 | + should 'redirect to login after user not logged asks to join a community' do |
| 478 | community = Community.create!(:name => 'my test community') | 478 | community = Community.create!(:name => 'my test community') |
| 479 | 479 | ||
| 480 | - @request.expects(:referer).returns("/profile/#{community.identifier}/to_go") | ||
| 481 | - login_as(profile.identifier) | 480 | + get :join_not_logged, :profile => community.identifier |
| 482 | 481 | ||
| 483 | - post :join_not_logged, :profile => community.identifier | 482 | + assert_equal community.identifier, @request.session[:join] |
| 483 | + assert_redirected_to :controller => :account, :action => :login | ||
| 484 | + end | ||
| 484 | 485 | ||
| 485 | - assert_redirected_to "/profile/#{community.identifier}/to_go" | 486 | + should 'redirect to join after user logged asks to join_not_logged a community' do |
| 487 | + community = Community.create!(:name => 'my test community') | ||
| 488 | + | ||
| 489 | + login_as(profile.identifier) | ||
| 490 | + get :join_not_logged, :profile => community.identifier | ||
| 486 | 491 | ||
| 487 | - assert_nil @request.session[:previous_location] | 492 | + assert_equal community.identifier, @request.session[:join] |
| 493 | + assert_redirected_to :controller => :profile, :action => :join | ||
| 488 | end | 494 | end |
| 489 | 495 | ||
| 490 | should 'show number of published events in index' do | 496 | should 'show number of published events in index' do |
| @@ -1186,7 +1192,7 @@ class ProfileControllerTest < ActionController::TestCase | @@ -1186,7 +1192,7 @@ class ProfileControllerTest < ActionController::TestCase | ||
| 1186 | 20.times {comment = fast_create(Comment, :source_id => article, :title => 'a comment', :body => 'lalala', :created_at => Time.now)} | 1192 | 20.times {comment = fast_create(Comment, :source_id => article, :title => 'a comment', :body => 'lalala', :created_at => Time.now)} |
| 1187 | article.reload | 1193 | article.reload |
| 1188 | get :index, :profile => profile.identifier | 1194 | get :index, :profile => profile.identifier |
| 1189 | - assert_tag 'ul', :attributes => {:class => 'profile-wall-activities-comments'}, :children => {:count => 0 } | 1195 | + assert_tag 'ul', :attributes => {:class => 'profile-wall-activities-comments'}, :children => {:count => 0 } |
| 1190 | end | 1196 | end |
| 1191 | 1197 | ||
| 1192 | should "view more comments paginated" do | 1198 | should "view more comments paginated" do |
| @@ -1212,7 +1218,7 @@ class ProfileControllerTest < ActionController::TestCase | @@ -1212,7 +1218,7 @@ class ProfileControllerTest < ActionController::TestCase | ||
| 1212 | 20.times {fast_create(Scrap, :sender_id => profile.id, :receiver_id => profile.id, :scrap_id => scrap.id)} | 1218 | 20.times {fast_create(Scrap, :sender_id => profile.id, :receiver_id => profile.id, :scrap_id => scrap.id)} |
| 1213 | profile.reload | 1219 | profile.reload |
| 1214 | get :index, :profile => profile.identifier | 1220 | get :index, :profile => profile.identifier |
| 1215 | - assert_tag 'ul', :attributes => {:class => 'profile-wall-activities-comments scrap-replies'}, :children => {:count => 0 } | 1221 | + assert_tag 'ul', :attributes => {:class => 'profile-wall-activities-comments scrap-replies'}, :children => {:count => 0 } |
| 1216 | end | 1222 | end |
| 1217 | 1223 | ||
| 1218 | should "view more replies paginated" do | 1224 | should "view more replies paginated" do |
| @@ -1269,15 +1275,6 @@ class ProfileControllerTest < ActionController::TestCase | @@ -1269,15 +1275,6 @@ class ProfileControllerTest < ActionController::TestCase | ||
| 1269 | assert_tag :tag => 'div', :content => /#{instance_eval(&plugin2.profile_tabs[:content])}/, :attributes => {:id => /#{plugin2.profile_tabs[:id]}/} | 1275 | assert_tag :tag => 'div', :content => /#{instance_eval(&plugin2.profile_tabs[:content])}/, :attributes => {:id => /#{plugin2.profile_tabs[:id]}/} |
| 1270 | end | 1276 | end |
| 1271 | 1277 | ||
| 1272 | - should 'redirect to profile page when try to request join_not_logged via GET method' do | ||
| 1273 | - community = Community.create!(:name => 'my test community') | ||
| 1274 | - login_as(profile.identifier) | ||
| 1275 | - get :join_not_logged, :profile => community.identifier | ||
| 1276 | - assert_nothing_raised do | ||
| 1277 | - assert_redirected_to community.url | ||
| 1278 | - end | ||
| 1279 | - end | ||
| 1280 | - | ||
| 1281 | should 'check different profile from the domain profile' do | 1278 | should 'check different profile from the domain profile' do |
| 1282 | default = Environment.default | 1279 | default = Environment.default |
| 1283 | default.domains.create!(:name => 'environment.com') | 1280 | default.domains.create!(:name => 'environment.com') |
test/functional/profile_editor_controller_test.rb
| @@ -894,6 +894,23 @@ class ProfileEditorControllerTest < ActionController::TestCase | @@ -894,6 +894,23 @@ class ProfileEditorControllerTest < ActionController::TestCase | ||
| 894 | assert_tag :tag => 'input', :attributes => {:id => 'field_added_by_plugin', :value => 'value_of_field_added_by_plugin'} | 894 | assert_tag :tag => 'input', :attributes => {:id => 'field_added_by_plugin', :value => 'value_of_field_added_by_plugin'} |
| 895 | end | 895 | end |
| 896 | 896 | ||
| 897 | + should 'add extra content with block provided by plugins on edit' do | ||
| 898 | + class TestProfileEditPlugin < Noosfero::Plugin | ||
| 899 | + def profile_editor_extras | ||
| 900 | + lambda do | ||
| 901 | + render :text => "<input id='field_added_by_plugin' value='value_of_field_added_by_plugin'/>" | ||
| 902 | + end | ||
| 903 | + end | ||
| 904 | + end | ||
| 905 | + Noosfero::Plugin.stubs(:all).returns([TestProfileEditPlugin.to_s]) | ||
| 906 | + | ||
| 907 | + Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestProfileEditPlugin.new]) | ||
| 908 | + | ||
| 909 | + get :edit, :profile => profile.identifier | ||
| 910 | + | ||
| 911 | + assert_tag :tag => 'input', :attributes => {:id => 'field_added_by_plugin', :value => 'value_of_field_added_by_plugin'} | ||
| 912 | + end | ||
| 913 | + | ||
| 897 | should 'show image upload field from profile editor' do | 914 | should 'show image upload field from profile editor' do |
| 898 | env = Environment.default | 915 | env = Environment.default |
| 899 | env.custom_person_fields = { } | 916 | env.custom_person_fields = { } |