From 81752a5ce130ca0930ed23144f1475c673c6713f Mon Sep 17 00:00:00 2001 From: Rodrigo Souto Date: Mon, 10 Sep 2012 16:47:09 -0300 Subject: [PATCH] [custom-forms] Base model and migrations --- plugins/custom_forms/db/migrate/20120727162444_create_custom_forms_plugin_forms.rb | 20 ++++++++++++++++++++ plugins/custom_forms/db/migrate/20120727174506_create_custom_forms_plugin_fields.rb | 21 +++++++++++++++++++++ plugins/custom_forms/db/migrate/20120727175250_create_custom_forms_plugin_answers.rb | 13 +++++++++++++ plugins/custom_forms/db/migrate/20120727180512_create_custom_forms_plugin_submissions.rb | 15 +++++++++++++++ plugins/custom_forms/lib/custom_forms_plugin.rb | 21 +++++++++++++++++++++ plugins/custom_forms/lib/custom_forms_plugin/answer.rb | 14 ++++++++++++++ plugins/custom_forms/lib/custom_forms_plugin/field.rb | 16 ++++++++++++++++ plugins/custom_forms/lib/custom_forms_plugin/form.rb | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/custom_forms/lib/custom_forms_plugin/helper.rb | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/custom_forms/lib/custom_forms_plugin/membership_survey.rb | 47 +++++++++++++++++++++++++++++++++++++++++++++++ plugins/custom_forms/lib/custom_forms_plugin/numeric.rb | 4 ++++ plugins/custom_forms/lib/custom_forms_plugin/select_field.rb | 4 ++++ plugins/custom_forms/lib/custom_forms_plugin/submission.rb | 12 ++++++++++++ plugins/custom_forms/lib/custom_forms_plugin/text_field.rb | 3 +++ plugins/custom_forms/lib/ext/role_assignment_trigger.rb | 30 ++++++++++++++++++++++++++++++ plugins/custom_forms/test/unit/custom_forms_plugin/answer_test.rb | 38 ++++++++++++++++++++++++++++++++++++++ plugins/custom_forms/test/unit/custom_forms_plugin/field_test.rb | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/custom_forms/test/unit/custom_forms_plugin/form_test.rb | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/custom_forms/test/unit/custom_forms_plugin/membership_survey_test.rb | 31 +++++++++++++++++++++++++++++++ plugins/custom_forms/test/unit/custom_forms_plugin/select_field_test.rb | 13 +++++++++++++ plugins/custom_forms/test/unit/custom_forms_plugin/submission_test.rb | 46 ++++++++++++++++++++++++++++++++++++++++++++++ plugins/custom_forms/test/unit/ext/role_assingment_test.rb | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 22 files changed, 824 insertions(+), 0 deletions(-) create mode 100644 plugins/custom_forms/db/migrate/20120727162444_create_custom_forms_plugin_forms.rb create mode 100644 plugins/custom_forms/db/migrate/20120727174506_create_custom_forms_plugin_fields.rb create mode 100644 plugins/custom_forms/db/migrate/20120727175250_create_custom_forms_plugin_answers.rb create mode 100644 plugins/custom_forms/db/migrate/20120727180512_create_custom_forms_plugin_submissions.rb create mode 100644 plugins/custom_forms/lib/custom_forms_plugin.rb create mode 100644 plugins/custom_forms/lib/custom_forms_plugin/answer.rb create mode 100644 plugins/custom_forms/lib/custom_forms_plugin/field.rb create mode 100644 plugins/custom_forms/lib/custom_forms_plugin/form.rb create mode 100644 plugins/custom_forms/lib/custom_forms_plugin/helper.rb create mode 100644 plugins/custom_forms/lib/custom_forms_plugin/membership_survey.rb create mode 100644 plugins/custom_forms/lib/custom_forms_plugin/numeric.rb create mode 100644 plugins/custom_forms/lib/custom_forms_plugin/select_field.rb create mode 100644 plugins/custom_forms/lib/custom_forms_plugin/submission.rb create mode 100644 plugins/custom_forms/lib/custom_forms_plugin/text_field.rb create mode 100644 plugins/custom_forms/lib/ext/role_assignment_trigger.rb create mode 100644 plugins/custom_forms/test/unit/custom_forms_plugin/answer_test.rb create mode 100644 plugins/custom_forms/test/unit/custom_forms_plugin/field_test.rb create mode 100644 plugins/custom_forms/test/unit/custom_forms_plugin/form_test.rb create mode 100644 plugins/custom_forms/test/unit/custom_forms_plugin/membership_survey_test.rb create mode 100644 plugins/custom_forms/test/unit/custom_forms_plugin/select_field_test.rb create mode 100644 plugins/custom_forms/test/unit/custom_forms_plugin/submission_test.rb create mode 100644 plugins/custom_forms/test/unit/ext/role_assingment_test.rb diff --git a/plugins/custom_forms/db/migrate/20120727162444_create_custom_forms_plugin_forms.rb b/plugins/custom_forms/db/migrate/20120727162444_create_custom_forms_plugin_forms.rb new file mode 100644 index 0000000..5a7ec08 --- /dev/null +++ b/plugins/custom_forms/db/migrate/20120727162444_create_custom_forms_plugin_forms.rb @@ -0,0 +1,20 @@ +class CreateCustomFormsPluginForms < ActiveRecord::Migration + def self.up + create_table :custom_forms_plugin_forms do |t| + t.string :name + t.string :slug + t.text :description + t.references :profile + t.datetime :begining + t.datetime :ending + t.boolean :report_submissions, :default => false + t.boolean :on_membership, :default => false + t.string :access + t.timestamps + end + end + + def self.down + drop_table :custom_forms_plugin_forms + end +end diff --git a/plugins/custom_forms/db/migrate/20120727174506_create_custom_forms_plugin_fields.rb b/plugins/custom_forms/db/migrate/20120727174506_create_custom_forms_plugin_fields.rb new file mode 100644 index 0000000..e72bc62 --- /dev/null +++ b/plugins/custom_forms/db/migrate/20120727174506_create_custom_forms_plugin_fields.rb @@ -0,0 +1,21 @@ +class CreateCustomFormsPluginFields < ActiveRecord::Migration + def self.up + create_table :custom_forms_plugin_fields do |t| + t.string :name + t.string :slug + t.string :type + t.string :default_value + t.string :choices + t.float :minimum + t.float :maximum + t.references :form + t.boolean :mandatory, :default => false + t.boolean :multiple + t.boolean :list + end + end + + def self.down + drop_table :custom_forms_plugin_fields + end +end diff --git a/plugins/custom_forms/db/migrate/20120727175250_create_custom_forms_plugin_answers.rb b/plugins/custom_forms/db/migrate/20120727175250_create_custom_forms_plugin_answers.rb new file mode 100644 index 0000000..4adf1f5 --- /dev/null +++ b/plugins/custom_forms/db/migrate/20120727175250_create_custom_forms_plugin_answers.rb @@ -0,0 +1,13 @@ +class CreateCustomFormsPluginAnswers < ActiveRecord::Migration + def self.up + create_table :custom_forms_plugin_answers do |t| + t.text :value + t.references :field + t.references :submission + end + end + + def self.down + drop_table :custom_forms_plugin_answers + end +end diff --git a/plugins/custom_forms/db/migrate/20120727180512_create_custom_forms_plugin_submissions.rb b/plugins/custom_forms/db/migrate/20120727180512_create_custom_forms_plugin_submissions.rb new file mode 100644 index 0000000..c855afb --- /dev/null +++ b/plugins/custom_forms/db/migrate/20120727180512_create_custom_forms_plugin_submissions.rb @@ -0,0 +1,15 @@ +class CreateCustomFormsPluginSubmissions < ActiveRecord::Migration + def self.up + create_table :custom_forms_plugin_submissions do |t| + t.string :author_name + t.string :author_email + t.references :profile + t.references :form + t.timestamps + end + end + + def self.down + drop_table :custom_forms_plugin_submissions + end +end diff --git a/plugins/custom_forms/lib/custom_forms_plugin.rb b/plugins/custom_forms/lib/custom_forms_plugin.rb new file mode 100644 index 0000000..c92aad3 --- /dev/null +++ b/plugins/custom_forms/lib/custom_forms_plugin.rb @@ -0,0 +1,21 @@ +require 'ext/role_assignment_trigger' + +class CustomFormsPlugin < Noosfero::Plugin + + def self.plugin_name + "Custom Forms" + end + + def self.plugin_description + _("Enables the creation of forms.") + end + + def stylesheet? + true + end + + def control_panel_buttons + {:title => _('Manage Forms'), :icon => 'custom-forms', :url => {:controller => 'custom_forms_plugin_myprofile'}} + end + +end diff --git a/plugins/custom_forms/lib/custom_forms_plugin/answer.rb b/plugins/custom_forms/lib/custom_forms_plugin/answer.rb new file mode 100644 index 0000000..418ef60 --- /dev/null +++ b/plugins/custom_forms/lib/custom_forms_plugin/answer.rb @@ -0,0 +1,14 @@ +class CustomFormsPlugin::Answer < Noosfero::Plugin::ActiveRecord + belongs_to :field, :class_name => 'CustomFormsPlugin::Field' + belongs_to :submission, :class_name => 'CustomFormsPlugin::Submission' + + validates_presence_of :field + validate :value_mandatory, :if => 'field.present?' + + def value_mandatory + if field.mandatory && value.blank? + errors.add(field.slug.to_sym, _("is mandatory.").fix_i18n) + end + end +end + diff --git a/plugins/custom_forms/lib/custom_forms_plugin/field.rb b/plugins/custom_forms/lib/custom_forms_plugin/field.rb new file mode 100644 index 0000000..f9e1670 --- /dev/null +++ b/plugins/custom_forms/lib/custom_forms_plugin/field.rb @@ -0,0 +1,16 @@ +class CustomFormsPlugin::Field < ActiveRecord::Base + set_table_name :custom_forms_plugin_fields + + validates_presence_of :form, :name + validates_uniqueness_of :slug, :scope => :form_id + + belongs_to :form, :class_name => 'CustomFormsPlugin::Form', :dependent => :destroy + has_many :answers, :class_name => 'CustomFormsPlugin::Answer' + + serialize :choices, Hash + + before_validation do |field| + field.slug = field.name.to_slug if field.name.present? + end +end + diff --git a/plugins/custom_forms/lib/custom_forms_plugin/form.rb b/plugins/custom_forms/lib/custom_forms_plugin/form.rb new file mode 100644 index 0000000..b7fa135 --- /dev/null +++ b/plugins/custom_forms/lib/custom_forms_plugin/form.rb @@ -0,0 +1,70 @@ +class CustomFormsPlugin::Form < Noosfero::Plugin::ActiveRecord + belongs_to :profile + + has_many :fields, :class_name => 'CustomFormsPlugin::Field' + has_many :submissions, :class_name => 'CustomFormsPlugin::Submission' + + serialize :access + + validates_presence_of :profile, :name + validates_uniqueness_of :slug, :scope => :profile_id + validate :access_format + + before_validation do |form| + form.slug = form.name.to_slug if form.name.present? + form.access = nil if form.access.blank? + end + + named_scope :from, lambda {|profile| {:conditions => {:profile_id => profile.id}}} + named_scope :on_memberships, {:conditions => {:on_membership => true}} +=begin + named_scope :accessible_to lambda do |profile| + #TODO should verify is profile is associated with the form owner + profile_associated = ??? + {:conditions => [" + access IS NULL OR + (access='logged' AND :profile_present) OR + (access='associated' AND :profile_associated) OR + :profile_id in access + ", {:profile_present => profile.present?, :profile_associated => ???, :profile_id => profile.id}]} + end +=end + + def expired? + (begining.present? && Time.now < begining) || (ending.present? && Time.now > ending) + end + + def accessible_to(target) + return true if access.nil? || target == profile + return false if target.nil? + return true if access == 'logged' + return true if access == 'associated' && ((profile.organization? && profile.members.include?(target)) || (profile.person? && profile.friends.include?(target))) + return true if access.kind_of?(Integer) && target.id == access + return true if access.kind_of?(Array) && access.include?(target.id) + end + + private + + def access_format + if access.present? + if access.kind_of?(String) + if access != 'logged' && access != 'associated' + errors.add(:access, _('Invalid string format of access.')) + end + elsif access.kind_of?(Integer) + if !Profile.exists?(access) + errors.add(:access, _('There is no profile with the provided id.')) + end + elsif access.kind_of?(Array) + access.each do |value| + if !value.kind_of?(Integer) || !Profile.exists?(value) + errors.add(:access, _('There is no profile with the provided id.')) + break + end + end + else + errors.add(:access, _('Invalid type format of access.')) + end + end + end +end diff --git a/plugins/custom_forms/lib/custom_forms_plugin/helper.rb b/plugins/custom_forms/lib/custom_forms_plugin/helper.rb new file mode 100644 index 0000000..e3929d8 --- /dev/null +++ b/plugins/custom_forms/lib/custom_forms_plugin/helper.rb @@ -0,0 +1,119 @@ +module CustomFormsPlugin::Helper + def access_text(form) + return _('Public') if form.access.nil? + return _('Logged users') if form.access == 'logged' + if form.access == 'associated' + return _('Members') if form.profile.organization? + return _('Friends') if form.profile.person? + end + return _('Custom') + end + + def period_range(form) + if form.begining.blank? && form.ending.blank? + _('Always') + elsif form.begining.present? && form.ending.blank? + ('From %s') % time_format(form.begining) + elsif form.begining.blank? && form.ending.present? + _('Until %s') % time_format(form.ending) + elsif form.begining.present? && form.ending.present? + _('From %s until %s') % [time_format(form.begining), time_format(form.ending)] + end + end + + def time_format(time) + minutes = (time.min == 0) ? '' : ':%M' + hour = (time.hour == 0 && minutes.blank?) ? '' : ' %H' + h = hour.blank? ? '' : 'h' + time.strftime("%Y-%m-%d#{hour+minutes+h}") + end + + # TODO add the custom option that should offer the user the hability to + # choose the profiles one by one, using something like tokeninput + def access_options(profile) + associated = profile.organization? ? _('Members') : _('Friends') + [ + [_('Public'), nil ], + [_('Logged users'), 'logged' ], + [ associated, 'associated'], + ] + end + + def type_options + [ + [_('Text'), 'text_field' ], + [_('Select'), 'select_field'] + ] + end + + def type_to_label(type) + map = { + 'text_field' => _('Text'), + 'select_field' => _('Select') + } + map[type_for_options(type)] + end + + def type_for_options(type) + type.to_s.split(':').last.underscore + end + + def display_custom_field(field, submission, form) + answer = submission.answers.select{|answer| answer.field == field}.first + field_tag = send("display_#{type_for_options(field.class)}",field, answer, form) + if field.mandatory? && !radio_button?(field) && !check_box?(field) && submission.id.nil? + required(labelled_form_field(field.name, field_tag)) + else + labelled_form_field(field.name, field_tag) + end + end + + def display_text_field(field, answer, form) + value = answer.present? ? answer.value : field.default_value + text_field(form, field.name.to_slug, :value => value, :disabled => answer.present?) + end + + def display_select_field(field, answer, form) + if field.list && field.multiple + selected = answer.present? ? answer.value.split(',') : [] + select_tag "#{form}[#{field.name.to_slug}]", options_for_select(field.choices.to_a, selected), :multiple => true, :size => field.choices.size, :disabled => answer.present? + elsif !field.list && field.multiple + field.choices.map do |name, value| + default = answer.present? ? answer.value.split(',').include?(value) : false + labelled_check_box name, "#{form}[#{field.name.to_slug}][#{value}]", '1', default, :disabled => answer.present? + end.join("\n") + elsif field.list && !field.multiple + selected = answer.present? ? answer.value.split(',') : [] + select_tag "#{form}[#{field.name.to_slug}]", options_for_select([['','']] + field.choices.to_a, selected), :disabled => answer.present? + elsif !field.list && !field.multiple + field.choices.map do |name, value| + default = answer.present? ? answer.value == value : true + labelled_radio_button name, "#{form}[#{field.name.to_slug}]", value, default, :disabled => answer.present? + end.join("\n") + end + end + + def radio_button?(field) + type_for_options(field.class) == 'select_field' && !field.list && !field.multiple + end + + def check_box?(field) + type_for_options(field.class) == 'select_field' && !field.list && field.multiple + end + + def build_answers(submission, form) + answers = [] + submission.each do |slug, value| + field = form.fields.select {|field| field.slug==slug}.first + if value.kind_of?(String) + final_value = value + elsif value.kind_of?(Array) + final_value = value.join(',') + elsif value.kind_of?(Hash) + final_value = value.map {|option, present| present == '1' ? option : nil}.compact.join(',') + end + answers << CustomFormsPlugin::Answer.new(:field => field, :value => final_value) + end + answers + end +end diff --git a/plugins/custom_forms/lib/custom_forms_plugin/membership_survey.rb b/plugins/custom_forms/lib/custom_forms_plugin/membership_survey.rb new file mode 100644 index 0000000..a57cb50 --- /dev/null +++ b/plugins/custom_forms/lib/custom_forms_plugin/membership_survey.rb @@ -0,0 +1,47 @@ +class CustomFormsPlugin::MembershipSurvey < Task + + settings_items :form_id, :submission + validates_presence_of :form_id + + include CustomFormsPlugin::Helper + + def perform + form = CustomFormsPlugin::Form.find(form_id) + answers = build_answers(submission, form) + s = CustomFormsPlugin::Submission.create!(:form => form, :profile => target) + answers.map {|answer| answer.submission = s; answer.save!} + end + + def title + _("Membership survey") + end + + def subject + nil + end + + def linked_subject + nil + end + + def information + {:message => _('%{requestor} wants you to fill in some information.')} + end + + def accept_details + true + end + + def icon + {:type => :profile_image, :profile => requestor, :url => requestor.url} + end + + def target_notification_message + _('After joining %{requestor}, the administrators of this organization + wants you to fill in some further information.') % {:requestor => requestor.name} + end + + def target_notification_description + _('%{requestor} wants to fill in some further information.') % {:requestor => requestor.name} + end +end diff --git a/plugins/custom_forms/lib/custom_forms_plugin/numeric.rb b/plugins/custom_forms/lib/custom_forms_plugin/numeric.rb new file mode 100644 index 0000000..abb3ddd --- /dev/null +++ b/plugins/custom_forms/lib/custom_forms_plugin/numeric.rb @@ -0,0 +1,4 @@ +class CustomFormsPlugin::Numeric < CustomFormsPlugin::Field + set_table_name :custom_forms_plugin_fields +end + diff --git a/plugins/custom_forms/lib/custom_forms_plugin/select_field.rb b/plugins/custom_forms/lib/custom_forms_plugin/select_field.rb new file mode 100644 index 0000000..d5bf84e --- /dev/null +++ b/plugins/custom_forms/lib/custom_forms_plugin/select_field.rb @@ -0,0 +1,4 @@ +class CustomFormsPlugin::SelectField < CustomFormsPlugin::Field + set_table_name :custom_forms_plugin_fields + validates_presence_of :choices +end diff --git a/plugins/custom_forms/lib/custom_forms_plugin/submission.rb b/plugins/custom_forms/lib/custom_forms_plugin/submission.rb new file mode 100644 index 0000000..371cb4b --- /dev/null +++ b/plugins/custom_forms/lib/custom_forms_plugin/submission.rb @@ -0,0 +1,12 @@ +class CustomFormsPlugin::Submission < Noosfero::Plugin::ActiveRecord + belongs_to :form, :class_name => 'CustomFormsPlugin::Form' + belongs_to :profile + + has_many :answers, :class_name => 'CustomFormsPlugin::Answer' + + validates_presence_of :form + validates_presence_of :author_name, :author_email, :if => lambda {|submission| submission.profile.nil?} + validates_uniqueness_of :author_email, :scope => :form_id, :allow_nil => true + validates_format_of :author_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda {|submission| !submission.author_email.blank?}) +end + diff --git a/plugins/custom_forms/lib/custom_forms_plugin/text_field.rb b/plugins/custom_forms/lib/custom_forms_plugin/text_field.rb new file mode 100644 index 0000000..9524a81 --- /dev/null +++ b/plugins/custom_forms/lib/custom_forms_plugin/text_field.rb @@ -0,0 +1,3 @@ +class CustomFormsPlugin::TextField < CustomFormsPlugin::Field + set_table_name :custom_forms_plugin_fields +end diff --git a/plugins/custom_forms/lib/ext/role_assignment_trigger.rb b/plugins/custom_forms/lib/ext/role_assignment_trigger.rb new file mode 100644 index 0000000..b499f33 --- /dev/null +++ b/plugins/custom_forms/lib/ext/role_assignment_trigger.rb @@ -0,0 +1,30 @@ +module RoleAssignmentTrigger + def self.included(base) + base.class_eval do + before_create do |ra| + profile = ra.resource + person = ra.accessor + ok = !profile.nil? && !person.nil? && profile.environment.present? + if ok && profile.environment.plugin_enabled?(CustomFormsPlugin) && !person.is_member_of?(profile) + CustomFormsPlugin::Form.from(profile).on_memberships.each do |form| + CustomFormsPlugin::MembershipSurvey.create!(:requestor => profile, :target => person, :form_id => form.id) + end + end + end + + after_destroy do |ra| + profile = ra.resource + person = ra.accessor + ok = !profile.nil? && !person.nil? && profile.environment.present? + if ok && profile.environment.plugin_enabled?(CustomFormsPlugin) && !person.is_member_of?(profile) + CustomFormsPlugin::Form.from(profile).on_memberships.each do |form| + task = person.tasks.pending.select {|task| task.kind_of?(CustomFormsPlugin::MembershipSurvey) && task.form_id == form.id}.first + task.cancel if task + end + end + end + end + end +end + +RoleAssignment.send :include, RoleAssignmentTrigger diff --git a/plugins/custom_forms/test/unit/custom_forms_plugin/answer_test.rb b/plugins/custom_forms/test/unit/custom_forms_plugin/answer_test.rb new file mode 100644 index 0000000..5e8b224 --- /dev/null +++ b/plugins/custom_forms/test/unit/custom_forms_plugin/answer_test.rb @@ -0,0 +1,38 @@ +require File.dirname(__FILE__) + '/../../../../../test/test_helper' + +class CustomFormsPlugin::AnswerTest < ActiveSupport::TestCase + should 'validates presence of field' do + answer = CustomFormsPlugin::Answer.new + answer.valid? + assert answer.errors.invalid?(:field) + + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) + field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form) + answer.field = field + answer.valid? + assert !answer.errors.invalid?(:field) + end + + should 'belong to a submission' do + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) + submission = CustomFormsPlugin::Submission.create!(:form => form, :profile => fast_create(Profile)) + answer = CustomFormsPlugin::Answer.new + answer.submission = submission + + assert_equal submission, answer.submission + end + + should 'require presence of value if field is mandatory' do + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) + field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form, :mandatory => true) + answer = CustomFormsPlugin::Answer.new(:field => field) + answer.valid? + assert answer.errors.invalid?(field.slug.to_sym) + + answer.value = "GPL" + answer.valid? + assert !answer.errors.invalid?(field.slug.to_sym) + end + +end + diff --git a/plugins/custom_forms/test/unit/custom_forms_plugin/field_test.rb b/plugins/custom_forms/test/unit/custom_forms_plugin/field_test.rb new file mode 100644 index 0000000..8262385 --- /dev/null +++ b/plugins/custom_forms/test/unit/custom_forms_plugin/field_test.rb @@ -0,0 +1,64 @@ +require File.dirname(__FILE__) + '/../../../../../test/test_helper' + +class CustomFormsPlugin::FieldTest < ActiveSupport::TestCase + should 'validate presence of form' do + field = CustomFormsPlugin::Field.new + field.valid? + assert field.errors.invalid?(:form) + assert field.errors.invalid?(:name) + + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) + field.form = form + field.name = 'License' + field.valid? + assert !field.errors.invalid?(:form) + assert !field.errors.invalid?(:name) + end + + should 'set slug before validation based on name' do + field = CustomFormsPlugin::Field.new(:name => 'Name') + field.valid? + assert_equal field.name.to_slug, field.slug + end + + should 'validate uniqueness of slug scoped on the form' do + form1 = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) + form2 = CustomFormsPlugin::Form.create!(:name => 'Open Source', :profile => fast_create(Profile)) + f1 = CustomFormsPlugin::Field.create!(:name => 'License', :form => form1) + f2 = CustomFormsPlugin::Field.new(:name => 'License', :form => form1) + f3 = CustomFormsPlugin::Field.new(:name => 'License', :form => form2) + + f2.valid? + f3.valid? + + assert f2.errors.invalid?(:slug) + assert !f3.errors.invalid?(:slug) + end + + should 'set mandatory field as false by default' do + field = CustomFormsPlugin::Field.new + assert !field.mandatory + end + + should 'have answers' do + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) + field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form) + a1 = CustomFormsPlugin::Answer.create!(:field => field) + a2 = CustomFormsPlugin::Answer.create!(:field => field) + + assert_includes field.answers, a1 + assert_includes field.answers, a2 + end + + should 'serialize choices into a hash' do + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) + field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form) + field.choices = {'First' => 1, 'Second' => 2, 'Third' => 3} + field.save! + + assert_equal 1, field.choices['First'] + assert_equal 2, field.choices['Second'] + assert_equal 3, field.choices['Third'] + end +end + diff --git a/plugins/custom_forms/test/unit/custom_forms_plugin/form_test.rb b/plugins/custom_forms/test/unit/custom_forms_plugin/form_test.rb new file mode 100644 index 0000000..09ccb85 --- /dev/null +++ b/plugins/custom_forms/test/unit/custom_forms_plugin/form_test.rb @@ -0,0 +1,172 @@ +require File.dirname(__FILE__) + '/../../../../../test/test_helper' + +class CustomFormsPlugin::FormTest < ActiveSupport::TestCase + should 'validates presence of a profile and a name' do + form = CustomFormsPlugin::Form.new + form.valid? + assert form.errors.invalid?(:profile) + assert form.errors.invalid?(:name) + + form.profile = fast_create(Profile) + form.name = 'Free Software' + form.valid? + assert !form.errors.invalid?(:profile) + assert !form.errors.invalid?(:name) + end + + should 'have many fields including fields subclasses' do + form = CustomFormsPlugin::Form.create!(:profile => fast_create(Profile), :name => 'Free Software') + f1 = CustomFormsPlugin::Field.create!(:form => form, :name => 'License') + f2 = CustomFormsPlugin::Field.create!(:form => form, :name => 'Code') + f3 = CustomFormsPlugin::TextField.create!(:form => form, :name => 'Developer') + + assert_includes form.fields, f1 + assert_includes form.fields, f2 + assert_includes form.fields, f3 + end + + should 'have many submissions' do + form = CustomFormsPlugin::Form.create!(:profile => fast_create(Profile), :name => 'Free Software') + s1 = CustomFormsPlugin::Submission.create!(:form => form, :profile => fast_create(Profile)) + s2 = CustomFormsPlugin::Submission.create!(:form => form, :profile => fast_create(Profile)) + + assert_includes form.submissions, s1 + assert_includes form.submissions, s2 + end + + should 'set slug before validation based on name' do + form = CustomFormsPlugin::Form.new(:name => 'Name') + form.valid? + assert_equal form.name.to_slug, form.slug + end + + should 'validates uniqueness of slug scoped on profile' do + profile = fast_create(Profile) + another_profile = fast_create(Profile) + CustomFormsPlugin::Form.create!(:profile => profile, :name => 'Free Software') + form = CustomFormsPlugin::Form.new(:profile => profile, :name => 'Free Software') + form.valid? + assert form.errors.invalid?(:slug) + + form.profile = another_profile + form.valid? + assert !form.errors.invalid?(:slug) + end + + should 'define form expiration' do + form = CustomFormsPlugin::Form.new + assert !form.expired? + + form.begining = Time.now + 1.day + assert form.expired? + + form.begining = Time.now - 1.day + assert !form.expired? + + form.begining = nil + form.ending = Time.now + 1.day + assert !form.expired? + + form.ending = Time.now - 1.day + assert form.expired? + + form.begining = Time.now - 1.day + form.ending = Time.now + 1.day + assert !form.expired? + end + + should 'validates format of access' do + form = CustomFormsPlugin::Form.new + form.valid? + assert !form.errors.invalid?(:access) + + form.access = 'bli' + form.valid? + assert form.errors.invalid?(:access) + + form.access = 'logged' + form.valid? + assert !form.errors.invalid?(:access) + + form.access = 'associated' + form.valid? + assert !form.errors.invalid?(:access) + + form.access = {:bli => 1} + form.valid? + assert form.errors.invalid?(:access) + + form.access = 999 + form.valid? + assert form.errors.invalid?(:access) + + p1 = fast_create(Profile) + form.access = p1.id + form.valid? + assert !form.errors.invalid?(:access) + + p2 = fast_create(Profile) + p3 = fast_create(Profile) + form.access = [p1,p2,p3].map(&:id) + form.valid? + assert !form.errors.invalid?(:access) + end + + should 'defines who is able to access the form' do + owner = fast_create(Community) + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => owner) + assert form.accessible_to(nil) + + form.access = 'logged' + assert !form.accessible_to(nil) + person = fast_create(Person) + assert form.accessible_to(person) + + form.access = 'associated' + assert !form.accessible_to(person) + owner.add_member(person) + assert form.accessible_to(person) + + p1 = fast_create(Profile) + form.access = p1.id + assert !form.accessible_to(person) + assert form.accessible_to(p1) + + p2 = fast_create(Profile) + form.access = [person.id, p1.id] + assert form.accessible_to(person) + assert form.accessible_to(p1) + assert !form.accessible_to(p2) + form.access << p2.id + assert form.accessible_to(p2) + + assert form.accessible_to(owner) + end + + should 'have a named_scope that retrieve forms from a profile' do + profile = fast_create(Profile) + another_profile = fast_create(Profile) + f1 = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => profile) + f2 = CustomFormsPlugin::Form.create!(:name => 'Open Source', :profile => profile) + f3 = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => another_profile) + scope = CustomFormsPlugin::Form.from(profile) + + assert_equal ActiveRecord::NamedScope::Scope, scope.class + assert_includes scope, f1 + assert_includes scope, f2 + assert_not_includes scope, f3 + end + + should 'have a named_scope that retrieves all forms that are triggered on membership' do + profile = fast_create(Profile) + f1 = CustomFormsPlugin::Form.create!(:name => 'On membership 1', :profile => profile, :on_membership => true) + f2 = CustomFormsPlugin::Form.create!(:name => 'On membership 2', :profile => profile, :on_membership => true) + f3 = CustomFormsPlugin::Form.create!(:name => 'Not on memberhsip', :profile => profile, :on_membership => false) + scope = CustomFormsPlugin::Form.from(profile).on_memberships + + assert_equal ActiveRecord::NamedScope::Scope, scope.class + assert_includes scope, f1 + assert_includes scope, f2 + assert_not_includes scope, f3 + end +end diff --git a/plugins/custom_forms/test/unit/custom_forms_plugin/membership_survey_test.rb b/plugins/custom_forms/test/unit/custom_forms_plugin/membership_survey_test.rb new file mode 100644 index 0000000..72cd63a --- /dev/null +++ b/plugins/custom_forms/test/unit/custom_forms_plugin/membership_survey_test.rb @@ -0,0 +1,31 @@ +require File.dirname(__FILE__) + '/../../../../../test/test_helper' + +class CustomFormsPlugin::MembershipSurveyTest < ActiveSupport::TestCase + should 'validates presence of form_id' do + task = CustomFormsPlugin::MembershipSurvey.new + task.valid? + assert task.errors.invalid?(:form_id) + + task.form_id = 1 + task.valid? + assert !task.errors.invalid?(:form_id) + end + + should 'create submission with answers on perform' do + profile = fast_create(Profile) + person = fast_create(Person) + form = CustomFormsPlugin::Form.create!(:name => 'Simple Form', :profile => profile) + field = CustomFormsPlugin::Field.create!(:name => 'Name', :form => form) + task = CustomFormsPlugin::MembershipSurvey.create!(:form_id => form.id, :submission => {'name' => 'Jack'}, :target => person, :requestor => profile) + + assert_difference CustomFormsPlugin::Submission, :count, 1 do + task.finish + end + + submission = CustomFormsPlugin::Submission.last + assert_equal submission.answers.count, 1 + + answer = submission.answers.first + assert_equal answer.value, 'Jack' + end +end diff --git a/plugins/custom_forms/test/unit/custom_forms_plugin/select_field_test.rb b/plugins/custom_forms/test/unit/custom_forms_plugin/select_field_test.rb new file mode 100644 index 0000000..73de468 --- /dev/null +++ b/plugins/custom_forms/test/unit/custom_forms_plugin/select_field_test.rb @@ -0,0 +1,13 @@ +require File.dirname(__FILE__) + '/../../../../../test/test_helper' + +class CustomFormsPlugin::SelectFieldTest < ActiveSupport::TestCase + should 'validate presence of choices, multiple and list' do + select = CustomFormsPlugin::SelectField.new + select.valid? + assert select.errors.invalid?(:choices) + + select.choices = {'label' => 'value'} + select.valid? + assert !select.errors.invalid?(:choices) + end +end diff --git a/plugins/custom_forms/test/unit/custom_forms_plugin/submission_test.rb b/plugins/custom_forms/test/unit/custom_forms_plugin/submission_test.rb new file mode 100644 index 0000000..947404c --- /dev/null +++ b/plugins/custom_forms/test/unit/custom_forms_plugin/submission_test.rb @@ -0,0 +1,46 @@ +require File.dirname(__FILE__) + '/../../../../../test/test_helper' + +class CustomFormsPlugin::SubmissionTest < ActiveSupport::TestCase + should 'validates presence of form' do + submission = CustomFormsPlugin::Submission.new + submission.valid? + assert submission.errors.invalid?(:form) + + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) + submission.form = form + submission.valid? + assert !submission.errors.invalid?(:form) + end + + should 'belong to a profile' do + profile = fast_create(Profile) + submission = CustomFormsPlugin::Submission.new + submission.profile = profile + assert_equal profile, submission.profile + end + + should 'require presence of author name and email if profile is nil' do + submission = CustomFormsPlugin::Submission.new + submission.valid? + assert submission.errors.invalid?(:author_name) + assert submission.errors.invalid?(:author_email) + + submission.author_name = 'Jack Sparrow' + submission.author_email = 'jack@black-pearl.com' + submission.valid? + assert !submission.errors.invalid?(:author_name) + assert !submission.errors.invalid?(:author_email) + end + + should 'have answers' do + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) + field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form) + submission = CustomFormsPlugin::Submission.create!(:form => form, :profile => fast_create(Profile)) + a1 = CustomFormsPlugin::Answer.create!(:field => field, :submission => submission) + a2 = CustomFormsPlugin::Answer.create!(:field => field, :submission => submission) + + assert_includes submission.answers, a1 + assert_includes submission.answers, a2 + end +end + diff --git a/plugins/custom_forms/test/unit/ext/role_assingment_test.rb b/plugins/custom_forms/test/unit/ext/role_assingment_test.rb new file mode 100644 index 0000000..2d14999 --- /dev/null +++ b/plugins/custom_forms/test/unit/ext/role_assingment_test.rb @@ -0,0 +1,51 @@ +require File.dirname(__FILE__) + '/../../../../../test/test_helper' + +class RoleAssignmentsTest < ActiveSupport::TestCase + should 'create membership_surveys on membership creation' do + environment = Environment.default + environment.enable_plugin(CustomFormsPlugin) + organization = fast_create(Organization) + person = fast_create(Person) + f1 = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form 1', :on_membership => true) + f2 = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form 2', :on_membership => true) + f3 = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form 3', :on_membership => false) + + assert_difference CustomFormsPlugin::MembershipSurvey, :count, 2 do + organization.add_member(person) + end + end + + should 'create membership_survey on membership creation with form accessible to members only' do + environment = Environment.default + environment.enable_plugin(CustomFormsPlugin) + organization = fast_create(Organization) + person = fast_create(Person) + form = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form', :on_membership => true, :access => 'associated') + + assert_difference CustomFormsPlugin::MembershipSurvey, :count, 1 do + organization.add_member(person) + end + end + + should 'cancel membership_surveys if membership is undone and task is active' do + environment = Environment.default + environment.enable_plugin(CustomFormsPlugin) + organization = fast_create(Organization) + person = fast_create(Person) + form = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form', :on_membership => true) + organization.add_member(person) + + assert_difference CustomFormsPlugin::MembershipSurvey.pending, :count, -1 do + organization.remove_member(person) + end + + organization.add_member(person) + task = CustomFormsPlugin::MembershipSurvey.last + task.status = Task::Status::FINISHED + task.save! + assert_no_difference CustomFormsPlugin::MembershipSurvey.finished, :count do + organization.remove_member(person) + end + end +end + -- libgit2 0.21.2