Commit 81752a5ce130ca0930ed23144f1475c673c6713f
1 parent
76560478
Exists in
master
and in
23 other branches
[custom-forms] Base model and migrations
Showing
22 changed files
with
824 additions
and
0 deletions
Show diff stats
plugins/custom_forms/db/migrate/20120727162444_create_custom_forms_plugin_forms.rb
0 → 100644
| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | +class CreateCustomFormsPluginForms < ActiveRecord::Migration | |
| 2 | + def self.up | |
| 3 | + create_table :custom_forms_plugin_forms do |t| | |
| 4 | + t.string :name | |
| 5 | + t.string :slug | |
| 6 | + t.text :description | |
| 7 | + t.references :profile | |
| 8 | + t.datetime :begining | |
| 9 | + t.datetime :ending | |
| 10 | + t.boolean :report_submissions, :default => false | |
| 11 | + t.boolean :on_membership, :default => false | |
| 12 | + t.string :access | |
| 13 | + t.timestamps | |
| 14 | + end | |
| 15 | + end | |
| 16 | + | |
| 17 | + def self.down | |
| 18 | + drop_table :custom_forms_plugin_forms | |
| 19 | + end | |
| 20 | +end | ... | ... |
plugins/custom_forms/db/migrate/20120727174506_create_custom_forms_plugin_fields.rb
0 → 100644
| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | +class CreateCustomFormsPluginFields < ActiveRecord::Migration | |
| 2 | + def self.up | |
| 3 | + create_table :custom_forms_plugin_fields do |t| | |
| 4 | + t.string :name | |
| 5 | + t.string :slug | |
| 6 | + t.string :type | |
| 7 | + t.string :default_value | |
| 8 | + t.string :choices | |
| 9 | + t.float :minimum | |
| 10 | + t.float :maximum | |
| 11 | + t.references :form | |
| 12 | + t.boolean :mandatory, :default => false | |
| 13 | + t.boolean :multiple | |
| 14 | + t.boolean :list | |
| 15 | + end | |
| 16 | + end | |
| 17 | + | |
| 18 | + def self.down | |
| 19 | + drop_table :custom_forms_plugin_fields | |
| 20 | + end | |
| 21 | +end | ... | ... |
plugins/custom_forms/db/migrate/20120727175250_create_custom_forms_plugin_answers.rb
0 → 100644
| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | +class CreateCustomFormsPluginAnswers < ActiveRecord::Migration | |
| 2 | + def self.up | |
| 3 | + create_table :custom_forms_plugin_answers do |t| | |
| 4 | + t.text :value | |
| 5 | + t.references :field | |
| 6 | + t.references :submission | |
| 7 | + end | |
| 8 | + end | |
| 9 | + | |
| 10 | + def self.down | |
| 11 | + drop_table :custom_forms_plugin_answers | |
| 12 | + end | |
| 13 | +end | ... | ... |
plugins/custom_forms/db/migrate/20120727180512_create_custom_forms_plugin_submissions.rb
0 → 100644
| ... | ... | @@ -0,0 +1,15 @@ |
| 1 | +class CreateCustomFormsPluginSubmissions < ActiveRecord::Migration | |
| 2 | + def self.up | |
| 3 | + create_table :custom_forms_plugin_submissions do |t| | |
| 4 | + t.string :author_name | |
| 5 | + t.string :author_email | |
| 6 | + t.references :profile | |
| 7 | + t.references :form | |
| 8 | + t.timestamps | |
| 9 | + end | |
| 10 | + end | |
| 11 | + | |
| 12 | + def self.down | |
| 13 | + drop_table :custom_forms_plugin_submissions | |
| 14 | + end | |
| 15 | +end | ... | ... |
| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | +require 'ext/role_assignment_trigger' | |
| 2 | + | |
| 3 | +class CustomFormsPlugin < Noosfero::Plugin | |
| 4 | + | |
| 5 | + def self.plugin_name | |
| 6 | + "Custom Forms" | |
| 7 | + end | |
| 8 | + | |
| 9 | + def self.plugin_description | |
| 10 | + _("Enables the creation of forms.") | |
| 11 | + end | |
| 12 | + | |
| 13 | + def stylesheet? | |
| 14 | + true | |
| 15 | + end | |
| 16 | + | |
| 17 | + def control_panel_buttons | |
| 18 | + {:title => _('Manage Forms'), :icon => 'custom-forms', :url => {:controller => 'custom_forms_plugin_myprofile'}} | |
| 19 | + end | |
| 20 | + | |
| 21 | +end | ... | ... |
| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | +class CustomFormsPlugin::Answer < Noosfero::Plugin::ActiveRecord | |
| 2 | + belongs_to :field, :class_name => 'CustomFormsPlugin::Field' | |
| 3 | + belongs_to :submission, :class_name => 'CustomFormsPlugin::Submission' | |
| 4 | + | |
| 5 | + validates_presence_of :field | |
| 6 | + validate :value_mandatory, :if => 'field.present?' | |
| 7 | + | |
| 8 | + def value_mandatory | |
| 9 | + if field.mandatory && value.blank? | |
| 10 | + errors.add(field.slug.to_sym, _("is mandatory.").fix_i18n) | |
| 11 | + end | |
| 12 | + end | |
| 13 | +end | |
| 14 | + | ... | ... |
| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | +class CustomFormsPlugin::Field < ActiveRecord::Base | |
| 2 | + set_table_name :custom_forms_plugin_fields | |
| 3 | + | |
| 4 | + validates_presence_of :form, :name | |
| 5 | + validates_uniqueness_of :slug, :scope => :form_id | |
| 6 | + | |
| 7 | + belongs_to :form, :class_name => 'CustomFormsPlugin::Form', :dependent => :destroy | |
| 8 | + has_many :answers, :class_name => 'CustomFormsPlugin::Answer' | |
| 9 | + | |
| 10 | + serialize :choices, Hash | |
| 11 | + | |
| 12 | + before_validation do |field| | |
| 13 | + field.slug = field.name.to_slug if field.name.present? | |
| 14 | + end | |
| 15 | +end | |
| 16 | + | ... | ... |
| ... | ... | @@ -0,0 +1,70 @@ |
| 1 | +class CustomFormsPlugin::Form < Noosfero::Plugin::ActiveRecord | |
| 2 | + belongs_to :profile | |
| 3 | + | |
| 4 | + has_many :fields, :class_name => 'CustomFormsPlugin::Field' | |
| 5 | + has_many :submissions, :class_name => 'CustomFormsPlugin::Submission' | |
| 6 | + | |
| 7 | + serialize :access | |
| 8 | + | |
| 9 | + validates_presence_of :profile, :name | |
| 10 | + validates_uniqueness_of :slug, :scope => :profile_id | |
| 11 | + validate :access_format | |
| 12 | + | |
| 13 | + before_validation do |form| | |
| 14 | + form.slug = form.name.to_slug if form.name.present? | |
| 15 | + form.access = nil if form.access.blank? | |
| 16 | + end | |
| 17 | + | |
| 18 | + named_scope :from, lambda {|profile| {:conditions => {:profile_id => profile.id}}} | |
| 19 | + named_scope :on_memberships, {:conditions => {:on_membership => true}} | |
| 20 | +=begin | |
| 21 | + named_scope :accessible_to lambda do |profile| | |
| 22 | + #TODO should verify is profile is associated with the form owner | |
| 23 | + profile_associated = ??? | |
| 24 | + {:conditions => [" | |
| 25 | + access IS NULL OR | |
| 26 | + (access='logged' AND :profile_present) OR | |
| 27 | + (access='associated' AND :profile_associated) OR | |
| 28 | + :profile_id in access | |
| 29 | + ", {:profile_present => profile.present?, :profile_associated => ???, :profile_id => profile.id}]} | |
| 30 | + end | |
| 31 | +=end | |
| 32 | + | |
| 33 | + def expired? | |
| 34 | + (begining.present? && Time.now < begining) || (ending.present? && Time.now > ending) | |
| 35 | + end | |
| 36 | + | |
| 37 | + def accessible_to(target) | |
| 38 | + return true if access.nil? || target == profile | |
| 39 | + return false if target.nil? | |
| 40 | + return true if access == 'logged' | |
| 41 | + return true if access == 'associated' && ((profile.organization? && profile.members.include?(target)) || (profile.person? && profile.friends.include?(target))) | |
| 42 | + return true if access.kind_of?(Integer) && target.id == access | |
| 43 | + return true if access.kind_of?(Array) && access.include?(target.id) | |
| 44 | + end | |
| 45 | + | |
| 46 | + private | |
| 47 | + | |
| 48 | + def access_format | |
| 49 | + if access.present? | |
| 50 | + if access.kind_of?(String) | |
| 51 | + if access != 'logged' && access != 'associated' | |
| 52 | + errors.add(:access, _('Invalid string format of access.')) | |
| 53 | + end | |
| 54 | + elsif access.kind_of?(Integer) | |
| 55 | + if !Profile.exists?(access) | |
| 56 | + errors.add(:access, _('There is no profile with the provided id.')) | |
| 57 | + end | |
| 58 | + elsif access.kind_of?(Array) | |
| 59 | + access.each do |value| | |
| 60 | + if !value.kind_of?(Integer) || !Profile.exists?(value) | |
| 61 | + errors.add(:access, _('There is no profile with the provided id.')) | |
| 62 | + break | |
| 63 | + end | |
| 64 | + end | |
| 65 | + else | |
| 66 | + errors.add(:access, _('Invalid type format of access.')) | |
| 67 | + end | |
| 68 | + end | |
| 69 | + end | |
| 70 | +end | ... | ... |
| ... | ... | @@ -0,0 +1,119 @@ |
| 1 | +module CustomFormsPlugin::Helper | |
| 2 | + def access_text(form) | |
| 3 | + return _('Public') if form.access.nil? | |
| 4 | + return _('Logged users') if form.access == 'logged' | |
| 5 | + if form.access == 'associated' | |
| 6 | + return _('Members') if form.profile.organization? | |
| 7 | + return _('Friends') if form.profile.person? | |
| 8 | + end | |
| 9 | + return _('Custom') | |
| 10 | + end | |
| 11 | + | |
| 12 | + def period_range(form) | |
| 13 | + if form.begining.blank? && form.ending.blank? | |
| 14 | + _('Always') | |
| 15 | + elsif form.begining.present? && form.ending.blank? | |
| 16 | + ('From %s') % time_format(form.begining) | |
| 17 | + elsif form.begining.blank? && form.ending.present? | |
| 18 | + _('Until %s') % time_format(form.ending) | |
| 19 | + elsif form.begining.present? && form.ending.present? | |
| 20 | + _('From %s until %s') % [time_format(form.begining), time_format(form.ending)] | |
| 21 | + end | |
| 22 | + end | |
| 23 | + | |
| 24 | + def time_format(time) | |
| 25 | + minutes = (time.min == 0) ? '' : ':%M' | |
| 26 | + hour = (time.hour == 0 && minutes.blank?) ? '' : ' %H' | |
| 27 | + h = hour.blank? ? '' : 'h' | |
| 28 | + time.strftime("%Y-%m-%d#{hour+minutes+h}") | |
| 29 | + end | |
| 30 | + | |
| 31 | + # TODO add the custom option that should offer the user the hability to | |
| 32 | + # choose the profiles one by one, using something like tokeninput | |
| 33 | + def access_options(profile) | |
| 34 | + associated = profile.organization? ? _('Members') : _('Friends') | |
| 35 | + [ | |
| 36 | + [_('Public'), nil ], | |
| 37 | + [_('Logged users'), 'logged' ], | |
| 38 | + [ associated, 'associated'], | |
| 39 | + ] | |
| 40 | + end | |
| 41 | + | |
| 42 | + def type_options | |
| 43 | + [ | |
| 44 | + [_('Text'), 'text_field' ], | |
| 45 | + [_('Select'), 'select_field'] | |
| 46 | + ] | |
| 47 | + end | |
| 48 | + | |
| 49 | + def type_to_label(type) | |
| 50 | + map = { | |
| 51 | + 'text_field' => _('Text'), | |
| 52 | + 'select_field' => _('Select') | |
| 53 | + } | |
| 54 | + map[type_for_options(type)] | |
| 55 | + end | |
| 56 | + | |
| 57 | + def type_for_options(type) | |
| 58 | + type.to_s.split(':').last.underscore | |
| 59 | + end | |
| 60 | + | |
| 61 | + def display_custom_field(field, submission, form) | |
| 62 | + answer = submission.answers.select{|answer| answer.field == field}.first | |
| 63 | + field_tag = send("display_#{type_for_options(field.class)}",field, answer, form) | |
| 64 | + if field.mandatory? && !radio_button?(field) && !check_box?(field) && submission.id.nil? | |
| 65 | + required(labelled_form_field(field.name, field_tag)) | |
| 66 | + else | |
| 67 | + labelled_form_field(field.name, field_tag) | |
| 68 | + end | |
| 69 | + end | |
| 70 | + | |
| 71 | + def display_text_field(field, answer, form) | |
| 72 | + value = answer.present? ? answer.value : field.default_value | |
| 73 | + text_field(form, field.name.to_slug, :value => value, :disabled => answer.present?) | |
| 74 | + end | |
| 75 | + | |
| 76 | + def display_select_field(field, answer, form) | |
| 77 | + if field.list && field.multiple | |
| 78 | + selected = answer.present? ? answer.value.split(',') : [] | |
| 79 | + select_tag "#{form}[#{field.name.to_slug}]", options_for_select(field.choices.to_a, selected), :multiple => true, :size => field.choices.size, :disabled => answer.present? | |
| 80 | + elsif !field.list && field.multiple | |
| 81 | + field.choices.map do |name, value| | |
| 82 | + default = answer.present? ? answer.value.split(',').include?(value) : false | |
| 83 | + labelled_check_box name, "#{form}[#{field.name.to_slug}][#{value}]", '1', default, :disabled => answer.present? | |
| 84 | + end.join("\n") | |
| 85 | + elsif field.list && !field.multiple | |
| 86 | + selected = answer.present? ? answer.value.split(',') : [] | |
| 87 | + select_tag "#{form}[#{field.name.to_slug}]", options_for_select([['','']] + field.choices.to_a, selected), :disabled => answer.present? | |
| 88 | + elsif !field.list && !field.multiple | |
| 89 | + field.choices.map do |name, value| | |
| 90 | + default = answer.present? ? answer.value == value : true | |
| 91 | + labelled_radio_button name, "#{form}[#{field.name.to_slug}]", value, default, :disabled => answer.present? | |
| 92 | + end.join("\n") | |
| 93 | + end | |
| 94 | + end | |
| 95 | + | |
| 96 | + def radio_button?(field) | |
| 97 | + type_for_options(field.class) == 'select_field' && !field.list && !field.multiple | |
| 98 | + end | |
| 99 | + | |
| 100 | + def check_box?(field) | |
| 101 | + type_for_options(field.class) == 'select_field' && !field.list && field.multiple | |
| 102 | + end | |
| 103 | + | |
| 104 | + def build_answers(submission, form) | |
| 105 | + answers = [] | |
| 106 | + submission.each do |slug, value| | |
| 107 | + field = form.fields.select {|field| field.slug==slug}.first | |
| 108 | + if value.kind_of?(String) | |
| 109 | + final_value = value | |
| 110 | + elsif value.kind_of?(Array) | |
| 111 | + final_value = value.join(',') | |
| 112 | + elsif value.kind_of?(Hash) | |
| 113 | + final_value = value.map {|option, present| present == '1' ? option : nil}.compact.join(',') | |
| 114 | + end | |
| 115 | + answers << CustomFormsPlugin::Answer.new(:field => field, :value => final_value) | |
| 116 | + end | |
| 117 | + answers | |
| 118 | + end | |
| 119 | +end | ... | ... |
plugins/custom_forms/lib/custom_forms_plugin/membership_survey.rb
0 → 100644
| ... | ... | @@ -0,0 +1,47 @@ |
| 1 | +class CustomFormsPlugin::MembershipSurvey < Task | |
| 2 | + | |
| 3 | + settings_items :form_id, :submission | |
| 4 | + validates_presence_of :form_id | |
| 5 | + | |
| 6 | + include CustomFormsPlugin::Helper | |
| 7 | + | |
| 8 | + def perform | |
| 9 | + form = CustomFormsPlugin::Form.find(form_id) | |
| 10 | + answers = build_answers(submission, form) | |
| 11 | + s = CustomFormsPlugin::Submission.create!(:form => form, :profile => target) | |
| 12 | + answers.map {|answer| answer.submission = s; answer.save!} | |
| 13 | + end | |
| 14 | + | |
| 15 | + def title | |
| 16 | + _("Membership survey") | |
| 17 | + end | |
| 18 | + | |
| 19 | + def subject | |
| 20 | + nil | |
| 21 | + end | |
| 22 | + | |
| 23 | + def linked_subject | |
| 24 | + nil | |
| 25 | + end | |
| 26 | + | |
| 27 | + def information | |
| 28 | + {:message => _('%{requestor} wants you to fill in some information.')} | |
| 29 | + end | |
| 30 | + | |
| 31 | + def accept_details | |
| 32 | + true | |
| 33 | + end | |
| 34 | + | |
| 35 | + def icon | |
| 36 | + {:type => :profile_image, :profile => requestor, :url => requestor.url} | |
| 37 | + end | |
| 38 | + | |
| 39 | + def target_notification_message | |
| 40 | + _('After joining %{requestor}, the administrators of this organization | |
| 41 | + wants you to fill in some further information.') % {:requestor => requestor.name} | |
| 42 | + end | |
| 43 | + | |
| 44 | + def target_notification_description | |
| 45 | + _('%{requestor} wants to fill in some further information.') % {:requestor => requestor.name} | |
| 46 | + end | |
| 47 | +end | ... | ... |
plugins/custom_forms/lib/custom_forms_plugin/select_field.rb
0 → 100644
plugins/custom_forms/lib/custom_forms_plugin/submission.rb
0 → 100644
| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | +class CustomFormsPlugin::Submission < Noosfero::Plugin::ActiveRecord | |
| 2 | + belongs_to :form, :class_name => 'CustomFormsPlugin::Form' | |
| 3 | + belongs_to :profile | |
| 4 | + | |
| 5 | + has_many :answers, :class_name => 'CustomFormsPlugin::Answer' | |
| 6 | + | |
| 7 | + validates_presence_of :form | |
| 8 | + validates_presence_of :author_name, :author_email, :if => lambda {|submission| submission.profile.nil?} | |
| 9 | + validates_uniqueness_of :author_email, :scope => :form_id, :allow_nil => true | |
| 10 | + validates_format_of :author_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda {|submission| !submission.author_email.blank?}) | |
| 11 | +end | |
| 12 | + | ... | ... |
plugins/custom_forms/lib/custom_forms_plugin/text_field.rb
0 → 100644
| ... | ... | @@ -0,0 +1,30 @@ |
| 1 | +module RoleAssignmentTrigger | |
| 2 | + def self.included(base) | |
| 3 | + base.class_eval do | |
| 4 | + before_create do |ra| | |
| 5 | + profile = ra.resource | |
| 6 | + person = ra.accessor | |
| 7 | + ok = !profile.nil? && !person.nil? && profile.environment.present? | |
| 8 | + if ok && profile.environment.plugin_enabled?(CustomFormsPlugin) && !person.is_member_of?(profile) | |
| 9 | + CustomFormsPlugin::Form.from(profile).on_memberships.each do |form| | |
| 10 | + CustomFormsPlugin::MembershipSurvey.create!(:requestor => profile, :target => person, :form_id => form.id) | |
| 11 | + end | |
| 12 | + end | |
| 13 | + end | |
| 14 | + | |
| 15 | + after_destroy do |ra| | |
| 16 | + profile = ra.resource | |
| 17 | + person = ra.accessor | |
| 18 | + ok = !profile.nil? && !person.nil? && profile.environment.present? | |
| 19 | + if ok && profile.environment.plugin_enabled?(CustomFormsPlugin) && !person.is_member_of?(profile) | |
| 20 | + CustomFormsPlugin::Form.from(profile).on_memberships.each do |form| | |
| 21 | + task = person.tasks.pending.select {|task| task.kind_of?(CustomFormsPlugin::MembershipSurvey) && task.form_id == form.id}.first | |
| 22 | + task.cancel if task | |
| 23 | + end | |
| 24 | + end | |
| 25 | + end | |
| 26 | + end | |
| 27 | + end | |
| 28 | +end | |
| 29 | + | |
| 30 | +RoleAssignment.send :include, RoleAssignmentTrigger | ... | ... |
plugins/custom_forms/test/unit/custom_forms_plugin/answer_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,38 @@ |
| 1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | |
| 2 | + | |
| 3 | +class CustomFormsPlugin::AnswerTest < ActiveSupport::TestCase | |
| 4 | + should 'validates presence of field' do | |
| 5 | + answer = CustomFormsPlugin::Answer.new | |
| 6 | + answer.valid? | |
| 7 | + assert answer.errors.invalid?(:field) | |
| 8 | + | |
| 9 | + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | |
| 10 | + field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form) | |
| 11 | + answer.field = field | |
| 12 | + answer.valid? | |
| 13 | + assert !answer.errors.invalid?(:field) | |
| 14 | + end | |
| 15 | + | |
| 16 | + should 'belong to a submission' do | |
| 17 | + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | |
| 18 | + submission = CustomFormsPlugin::Submission.create!(:form => form, :profile => fast_create(Profile)) | |
| 19 | + answer = CustomFormsPlugin::Answer.new | |
| 20 | + answer.submission = submission | |
| 21 | + | |
| 22 | + assert_equal submission, answer.submission | |
| 23 | + end | |
| 24 | + | |
| 25 | + should 'require presence of value if field is mandatory' do | |
| 26 | + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | |
| 27 | + field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form, :mandatory => true) | |
| 28 | + answer = CustomFormsPlugin::Answer.new(:field => field) | |
| 29 | + answer.valid? | |
| 30 | + assert answer.errors.invalid?(field.slug.to_sym) | |
| 31 | + | |
| 32 | + answer.value = "GPL" | |
| 33 | + answer.valid? | |
| 34 | + assert !answer.errors.invalid?(field.slug.to_sym) | |
| 35 | + end | |
| 36 | + | |
| 37 | +end | |
| 38 | + | ... | ... |
plugins/custom_forms/test/unit/custom_forms_plugin/field_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,64 @@ |
| 1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | |
| 2 | + | |
| 3 | +class CustomFormsPlugin::FieldTest < ActiveSupport::TestCase | |
| 4 | + should 'validate presence of form' do | |
| 5 | + field = CustomFormsPlugin::Field.new | |
| 6 | + field.valid? | |
| 7 | + assert field.errors.invalid?(:form) | |
| 8 | + assert field.errors.invalid?(:name) | |
| 9 | + | |
| 10 | + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | |
| 11 | + field.form = form | |
| 12 | + field.name = 'License' | |
| 13 | + field.valid? | |
| 14 | + assert !field.errors.invalid?(:form) | |
| 15 | + assert !field.errors.invalid?(:name) | |
| 16 | + end | |
| 17 | + | |
| 18 | + should 'set slug before validation based on name' do | |
| 19 | + field = CustomFormsPlugin::Field.new(:name => 'Name') | |
| 20 | + field.valid? | |
| 21 | + assert_equal field.name.to_slug, field.slug | |
| 22 | + end | |
| 23 | + | |
| 24 | + should 'validate uniqueness of slug scoped on the form' do | |
| 25 | + form1 = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | |
| 26 | + form2 = CustomFormsPlugin::Form.create!(:name => 'Open Source', :profile => fast_create(Profile)) | |
| 27 | + f1 = CustomFormsPlugin::Field.create!(:name => 'License', :form => form1) | |
| 28 | + f2 = CustomFormsPlugin::Field.new(:name => 'License', :form => form1) | |
| 29 | + f3 = CustomFormsPlugin::Field.new(:name => 'License', :form => form2) | |
| 30 | + | |
| 31 | + f2.valid? | |
| 32 | + f3.valid? | |
| 33 | + | |
| 34 | + assert f2.errors.invalid?(:slug) | |
| 35 | + assert !f3.errors.invalid?(:slug) | |
| 36 | + end | |
| 37 | + | |
| 38 | + should 'set mandatory field as false by default' do | |
| 39 | + field = CustomFormsPlugin::Field.new | |
| 40 | + assert !field.mandatory | |
| 41 | + end | |
| 42 | + | |
| 43 | + should 'have answers' do | |
| 44 | + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | |
| 45 | + field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form) | |
| 46 | + a1 = CustomFormsPlugin::Answer.create!(:field => field) | |
| 47 | + a2 = CustomFormsPlugin::Answer.create!(:field => field) | |
| 48 | + | |
| 49 | + assert_includes field.answers, a1 | |
| 50 | + assert_includes field.answers, a2 | |
| 51 | + end | |
| 52 | + | |
| 53 | + should 'serialize choices into a hash' do | |
| 54 | + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | |
| 55 | + field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form) | |
| 56 | + field.choices = {'First' => 1, 'Second' => 2, 'Third' => 3} | |
| 57 | + field.save! | |
| 58 | + | |
| 59 | + assert_equal 1, field.choices['First'] | |
| 60 | + assert_equal 2, field.choices['Second'] | |
| 61 | + assert_equal 3, field.choices['Third'] | |
| 62 | + end | |
| 63 | +end | |
| 64 | + | ... | ... |
plugins/custom_forms/test/unit/custom_forms_plugin/form_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,172 @@ |
| 1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | |
| 2 | + | |
| 3 | +class CustomFormsPlugin::FormTest < ActiveSupport::TestCase | |
| 4 | + should 'validates presence of a profile and a name' do | |
| 5 | + form = CustomFormsPlugin::Form.new | |
| 6 | + form.valid? | |
| 7 | + assert form.errors.invalid?(:profile) | |
| 8 | + assert form.errors.invalid?(:name) | |
| 9 | + | |
| 10 | + form.profile = fast_create(Profile) | |
| 11 | + form.name = 'Free Software' | |
| 12 | + form.valid? | |
| 13 | + assert !form.errors.invalid?(:profile) | |
| 14 | + assert !form.errors.invalid?(:name) | |
| 15 | + end | |
| 16 | + | |
| 17 | + should 'have many fields including fields subclasses' do | |
| 18 | + form = CustomFormsPlugin::Form.create!(:profile => fast_create(Profile), :name => 'Free Software') | |
| 19 | + f1 = CustomFormsPlugin::Field.create!(:form => form, :name => 'License') | |
| 20 | + f2 = CustomFormsPlugin::Field.create!(:form => form, :name => 'Code') | |
| 21 | + f3 = CustomFormsPlugin::TextField.create!(:form => form, :name => 'Developer') | |
| 22 | + | |
| 23 | + assert_includes form.fields, f1 | |
| 24 | + assert_includes form.fields, f2 | |
| 25 | + assert_includes form.fields, f3 | |
| 26 | + end | |
| 27 | + | |
| 28 | + should 'have many submissions' do | |
| 29 | + form = CustomFormsPlugin::Form.create!(:profile => fast_create(Profile), :name => 'Free Software') | |
| 30 | + s1 = CustomFormsPlugin::Submission.create!(:form => form, :profile => fast_create(Profile)) | |
| 31 | + s2 = CustomFormsPlugin::Submission.create!(:form => form, :profile => fast_create(Profile)) | |
| 32 | + | |
| 33 | + assert_includes form.submissions, s1 | |
| 34 | + assert_includes form.submissions, s2 | |
| 35 | + end | |
| 36 | + | |
| 37 | + should 'set slug before validation based on name' do | |
| 38 | + form = CustomFormsPlugin::Form.new(:name => 'Name') | |
| 39 | + form.valid? | |
| 40 | + assert_equal form.name.to_slug, form.slug | |
| 41 | + end | |
| 42 | + | |
| 43 | + should 'validates uniqueness of slug scoped on profile' do | |
| 44 | + profile = fast_create(Profile) | |
| 45 | + another_profile = fast_create(Profile) | |
| 46 | + CustomFormsPlugin::Form.create!(:profile => profile, :name => 'Free Software') | |
| 47 | + form = CustomFormsPlugin::Form.new(:profile => profile, :name => 'Free Software') | |
| 48 | + form.valid? | |
| 49 | + assert form.errors.invalid?(:slug) | |
| 50 | + | |
| 51 | + form.profile = another_profile | |
| 52 | + form.valid? | |
| 53 | + assert !form.errors.invalid?(:slug) | |
| 54 | + end | |
| 55 | + | |
| 56 | + should 'define form expiration' do | |
| 57 | + form = CustomFormsPlugin::Form.new | |
| 58 | + assert !form.expired? | |
| 59 | + | |
| 60 | + form.begining = Time.now + 1.day | |
| 61 | + assert form.expired? | |
| 62 | + | |
| 63 | + form.begining = Time.now - 1.day | |
| 64 | + assert !form.expired? | |
| 65 | + | |
| 66 | + form.begining = nil | |
| 67 | + form.ending = Time.now + 1.day | |
| 68 | + assert !form.expired? | |
| 69 | + | |
| 70 | + form.ending = Time.now - 1.day | |
| 71 | + assert form.expired? | |
| 72 | + | |
| 73 | + form.begining = Time.now - 1.day | |
| 74 | + form.ending = Time.now + 1.day | |
| 75 | + assert !form.expired? | |
| 76 | + end | |
| 77 | + | |
| 78 | + should 'validates format of access' do | |
| 79 | + form = CustomFormsPlugin::Form.new | |
| 80 | + form.valid? | |
| 81 | + assert !form.errors.invalid?(:access) | |
| 82 | + | |
| 83 | + form.access = 'bli' | |
| 84 | + form.valid? | |
| 85 | + assert form.errors.invalid?(:access) | |
| 86 | + | |
| 87 | + form.access = 'logged' | |
| 88 | + form.valid? | |
| 89 | + assert !form.errors.invalid?(:access) | |
| 90 | + | |
| 91 | + form.access = 'associated' | |
| 92 | + form.valid? | |
| 93 | + assert !form.errors.invalid?(:access) | |
| 94 | + | |
| 95 | + form.access = {:bli => 1} | |
| 96 | + form.valid? | |
| 97 | + assert form.errors.invalid?(:access) | |
| 98 | + | |
| 99 | + form.access = 999 | |
| 100 | + form.valid? | |
| 101 | + assert form.errors.invalid?(:access) | |
| 102 | + | |
| 103 | + p1 = fast_create(Profile) | |
| 104 | + form.access = p1.id | |
| 105 | + form.valid? | |
| 106 | + assert !form.errors.invalid?(:access) | |
| 107 | + | |
| 108 | + p2 = fast_create(Profile) | |
| 109 | + p3 = fast_create(Profile) | |
| 110 | + form.access = [p1,p2,p3].map(&:id) | |
| 111 | + form.valid? | |
| 112 | + assert !form.errors.invalid?(:access) | |
| 113 | + end | |
| 114 | + | |
| 115 | + should 'defines who is able to access the form' do | |
| 116 | + owner = fast_create(Community) | |
| 117 | + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => owner) | |
| 118 | + assert form.accessible_to(nil) | |
| 119 | + | |
| 120 | + form.access = 'logged' | |
| 121 | + assert !form.accessible_to(nil) | |
| 122 | + person = fast_create(Person) | |
| 123 | + assert form.accessible_to(person) | |
| 124 | + | |
| 125 | + form.access = 'associated' | |
| 126 | + assert !form.accessible_to(person) | |
| 127 | + owner.add_member(person) | |
| 128 | + assert form.accessible_to(person) | |
| 129 | + | |
| 130 | + p1 = fast_create(Profile) | |
| 131 | + form.access = p1.id | |
| 132 | + assert !form.accessible_to(person) | |
| 133 | + assert form.accessible_to(p1) | |
| 134 | + | |
| 135 | + p2 = fast_create(Profile) | |
| 136 | + form.access = [person.id, p1.id] | |
| 137 | + assert form.accessible_to(person) | |
| 138 | + assert form.accessible_to(p1) | |
| 139 | + assert !form.accessible_to(p2) | |
| 140 | + form.access << p2.id | |
| 141 | + assert form.accessible_to(p2) | |
| 142 | + | |
| 143 | + assert form.accessible_to(owner) | |
| 144 | + end | |
| 145 | + | |
| 146 | + should 'have a named_scope that retrieve forms from a profile' do | |
| 147 | + profile = fast_create(Profile) | |
| 148 | + another_profile = fast_create(Profile) | |
| 149 | + f1 = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => profile) | |
| 150 | + f2 = CustomFormsPlugin::Form.create!(:name => 'Open Source', :profile => profile) | |
| 151 | + f3 = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => another_profile) | |
| 152 | + scope = CustomFormsPlugin::Form.from(profile) | |
| 153 | + | |
| 154 | + assert_equal ActiveRecord::NamedScope::Scope, scope.class | |
| 155 | + assert_includes scope, f1 | |
| 156 | + assert_includes scope, f2 | |
| 157 | + assert_not_includes scope, f3 | |
| 158 | + end | |
| 159 | + | |
| 160 | + should 'have a named_scope that retrieves all forms that are triggered on membership' do | |
| 161 | + profile = fast_create(Profile) | |
| 162 | + f1 = CustomFormsPlugin::Form.create!(:name => 'On membership 1', :profile => profile, :on_membership => true) | |
| 163 | + f2 = CustomFormsPlugin::Form.create!(:name => 'On membership 2', :profile => profile, :on_membership => true) | |
| 164 | + f3 = CustomFormsPlugin::Form.create!(:name => 'Not on memberhsip', :profile => profile, :on_membership => false) | |
| 165 | + scope = CustomFormsPlugin::Form.from(profile).on_memberships | |
| 166 | + | |
| 167 | + assert_equal ActiveRecord::NamedScope::Scope, scope.class | |
| 168 | + assert_includes scope, f1 | |
| 169 | + assert_includes scope, f2 | |
| 170 | + assert_not_includes scope, f3 | |
| 171 | + end | |
| 172 | +end | ... | ... |
plugins/custom_forms/test/unit/custom_forms_plugin/membership_survey_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,31 @@ |
| 1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | |
| 2 | + | |
| 3 | +class CustomFormsPlugin::MembershipSurveyTest < ActiveSupport::TestCase | |
| 4 | + should 'validates presence of form_id' do | |
| 5 | + task = CustomFormsPlugin::MembershipSurvey.new | |
| 6 | + task.valid? | |
| 7 | + assert task.errors.invalid?(:form_id) | |
| 8 | + | |
| 9 | + task.form_id = 1 | |
| 10 | + task.valid? | |
| 11 | + assert !task.errors.invalid?(:form_id) | |
| 12 | + end | |
| 13 | + | |
| 14 | + should 'create submission with answers on perform' do | |
| 15 | + profile = fast_create(Profile) | |
| 16 | + person = fast_create(Person) | |
| 17 | + form = CustomFormsPlugin::Form.create!(:name => 'Simple Form', :profile => profile) | |
| 18 | + field = CustomFormsPlugin::Field.create!(:name => 'Name', :form => form) | |
| 19 | + task = CustomFormsPlugin::MembershipSurvey.create!(:form_id => form.id, :submission => {'name' => 'Jack'}, :target => person, :requestor => profile) | |
| 20 | + | |
| 21 | + assert_difference CustomFormsPlugin::Submission, :count, 1 do | |
| 22 | + task.finish | |
| 23 | + end | |
| 24 | + | |
| 25 | + submission = CustomFormsPlugin::Submission.last | |
| 26 | + assert_equal submission.answers.count, 1 | |
| 27 | + | |
| 28 | + answer = submission.answers.first | |
| 29 | + assert_equal answer.value, 'Jack' | |
| 30 | + end | |
| 31 | +end | ... | ... |
plugins/custom_forms/test/unit/custom_forms_plugin/select_field_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | |
| 2 | + | |
| 3 | +class CustomFormsPlugin::SelectFieldTest < ActiveSupport::TestCase | |
| 4 | + should 'validate presence of choices, multiple and list' do | |
| 5 | + select = CustomFormsPlugin::SelectField.new | |
| 6 | + select.valid? | |
| 7 | + assert select.errors.invalid?(:choices) | |
| 8 | + | |
| 9 | + select.choices = {'label' => 'value'} | |
| 10 | + select.valid? | |
| 11 | + assert !select.errors.invalid?(:choices) | |
| 12 | + end | |
| 13 | +end | ... | ... |
plugins/custom_forms/test/unit/custom_forms_plugin/submission_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,46 @@ |
| 1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | |
| 2 | + | |
| 3 | +class CustomFormsPlugin::SubmissionTest < ActiveSupport::TestCase | |
| 4 | + should 'validates presence of form' do | |
| 5 | + submission = CustomFormsPlugin::Submission.new | |
| 6 | + submission.valid? | |
| 7 | + assert submission.errors.invalid?(:form) | |
| 8 | + | |
| 9 | + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | |
| 10 | + submission.form = form | |
| 11 | + submission.valid? | |
| 12 | + assert !submission.errors.invalid?(:form) | |
| 13 | + end | |
| 14 | + | |
| 15 | + should 'belong to a profile' do | |
| 16 | + profile = fast_create(Profile) | |
| 17 | + submission = CustomFormsPlugin::Submission.new | |
| 18 | + submission.profile = profile | |
| 19 | + assert_equal profile, submission.profile | |
| 20 | + end | |
| 21 | + | |
| 22 | + should 'require presence of author name and email if profile is nil' do | |
| 23 | + submission = CustomFormsPlugin::Submission.new | |
| 24 | + submission.valid? | |
| 25 | + assert submission.errors.invalid?(:author_name) | |
| 26 | + assert submission.errors.invalid?(:author_email) | |
| 27 | + | |
| 28 | + submission.author_name = 'Jack Sparrow' | |
| 29 | + submission.author_email = 'jack@black-pearl.com' | |
| 30 | + submission.valid? | |
| 31 | + assert !submission.errors.invalid?(:author_name) | |
| 32 | + assert !submission.errors.invalid?(:author_email) | |
| 33 | + end | |
| 34 | + | |
| 35 | + should 'have answers' do | |
| 36 | + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | |
| 37 | + field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form) | |
| 38 | + submission = CustomFormsPlugin::Submission.create!(:form => form, :profile => fast_create(Profile)) | |
| 39 | + a1 = CustomFormsPlugin::Answer.create!(:field => field, :submission => submission) | |
| 40 | + a2 = CustomFormsPlugin::Answer.create!(:field => field, :submission => submission) | |
| 41 | + | |
| 42 | + assert_includes submission.answers, a1 | |
| 43 | + assert_includes submission.answers, a2 | |
| 44 | + end | |
| 45 | +end | |
| 46 | + | ... | ... |
plugins/custom_forms/test/unit/ext/role_assingment_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,51 @@ |
| 1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | |
| 2 | + | |
| 3 | +class RoleAssignmentsTest < ActiveSupport::TestCase | |
| 4 | + should 'create membership_surveys on membership creation' do | |
| 5 | + environment = Environment.default | |
| 6 | + environment.enable_plugin(CustomFormsPlugin) | |
| 7 | + organization = fast_create(Organization) | |
| 8 | + person = fast_create(Person) | |
| 9 | + f1 = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form 1', :on_membership => true) | |
| 10 | + f2 = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form 2', :on_membership => true) | |
| 11 | + f3 = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form 3', :on_membership => false) | |
| 12 | + | |
| 13 | + assert_difference CustomFormsPlugin::MembershipSurvey, :count, 2 do | |
| 14 | + organization.add_member(person) | |
| 15 | + end | |
| 16 | + end | |
| 17 | + | |
| 18 | + should 'create membership_survey on membership creation with form accessible to members only' do | |
| 19 | + environment = Environment.default | |
| 20 | + environment.enable_plugin(CustomFormsPlugin) | |
| 21 | + organization = fast_create(Organization) | |
| 22 | + person = fast_create(Person) | |
| 23 | + form = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form', :on_membership => true, :access => 'associated') | |
| 24 | + | |
| 25 | + assert_difference CustomFormsPlugin::MembershipSurvey, :count, 1 do | |
| 26 | + organization.add_member(person) | |
| 27 | + end | |
| 28 | + end | |
| 29 | + | |
| 30 | + should 'cancel membership_surveys if membership is undone and task is active' do | |
| 31 | + environment = Environment.default | |
| 32 | + environment.enable_plugin(CustomFormsPlugin) | |
| 33 | + organization = fast_create(Organization) | |
| 34 | + person = fast_create(Person) | |
| 35 | + form = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form', :on_membership => true) | |
| 36 | + organization.add_member(person) | |
| 37 | + | |
| 38 | + assert_difference CustomFormsPlugin::MembershipSurvey.pending, :count, -1 do | |
| 39 | + organization.remove_member(person) | |
| 40 | + end | |
| 41 | + | |
| 42 | + organization.add_member(person) | |
| 43 | + task = CustomFormsPlugin::MembershipSurvey.last | |
| 44 | + task.status = Task::Status::FINISHED | |
| 45 | + task.save! | |
| 46 | + assert_no_difference CustomFormsPlugin::MembershipSurvey.finished, :count do | |
| 47 | + organization.remove_member(person) | |
| 48 | + end | |
| 49 | + end | |
| 50 | +end | |
| 51 | + | ... | ... |