Commit 81752a5ce130ca0930ed23144f1475c673c6713f
1 parent
76560478
Exists in
master
and in
22 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 | + | ... | ... |