redmine_crm 0.0.23 → 0.0.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -1
  3. data/Gemfile +1 -1
  4. data/README.md +166 -33
  5. data/Rakefile +3 -12
  6. data/bitbucket-pipelines.yml +42 -0
  7. data/config/currency_iso.json +12 -0
  8. data/doc/CHANGELOG +81 -2
  9. data/lib/redmine_crm/acts_as_draftable/draft.rb +40 -0
  10. data/lib/redmine_crm/acts_as_draftable/rcrm_acts_as_draftable.rb +170 -0
  11. data/lib/redmine_crm/acts_as_list/list.rb +282 -0
  12. data/lib/redmine_crm/{rcrm_acts_as_taggable.rb → acts_as_taggable/rcrm_acts_as_taggable.rb} +105 -93
  13. data/lib/redmine_crm/acts_as_taggable/tag.rb +81 -0
  14. data/lib/redmine_crm/acts_as_taggable/tag_list.rb +111 -0
  15. data/lib/redmine_crm/acts_as_taggable/tagging.rb +16 -0
  16. data/lib/redmine_crm/acts_as_viewed/rcrm_acts_as_viewed.rb +274 -0
  17. data/lib/redmine_crm/{rcrm_acts_as_votable.rb → acts_as_votable/rcrm_acts_as_votable.rb} +15 -14
  18. data/lib/redmine_crm/acts_as_votable/rcrm_acts_as_voter.rb +20 -0
  19. data/lib/redmine_crm/{votable.rb → acts_as_votable/votable.rb} +54 -65
  20. data/lib/redmine_crm/{vote.rb → acts_as_votable/vote.rb} +6 -8
  21. data/lib/redmine_crm/{voter.rb → acts_as_votable/voter.rb} +29 -34
  22. data/lib/redmine_crm/assets_manager.rb +43 -0
  23. data/lib/redmine_crm/colors_helper.rb +192 -0
  24. data/lib/redmine_crm/compatibility/application_controller_patch.rb +33 -0
  25. data/lib/redmine_crm/currency/formatting.rb +0 -3
  26. data/lib/redmine_crm/currency/heuristics.rb +1 -1
  27. data/lib/redmine_crm/currency/loader.rb +5 -6
  28. data/lib/redmine_crm/helpers/external_assets_helper.rb +19 -0
  29. data/lib/redmine_crm/helpers/form_tag_helper.rb +76 -0
  30. data/lib/redmine_crm/helpers/tags_helper.rb +1 -3
  31. data/lib/redmine_crm/helpers/vote_helper.rb +29 -32
  32. data/lib/redmine_crm/liquid/drops/issues_drop.rb +191 -0
  33. data/lib/redmine_crm/liquid/drops/news_drop.rb +54 -0
  34. data/lib/redmine_crm/liquid/drops/projects_drop.rb +86 -0
  35. data/lib/redmine_crm/liquid/drops/time_entries_drop.rb +65 -0
  36. data/lib/redmine_crm/liquid/drops/users_drop.rb +68 -0
  37. data/lib/redmine_crm/liquid/filters/arrays.rb +187 -0
  38. data/lib/redmine_crm/liquid/filters/base.rb +217 -0
  39. data/lib/redmine_crm/liquid/filters/colors.rb +31 -0
  40. data/lib/redmine_crm/money_helper.rb +2 -4
  41. data/lib/redmine_crm/version.rb +1 -1
  42. data/lib/redmine_crm.rb +56 -21
  43. data/redmine_crm.gemspec +9 -4
  44. data/test/acts_as_draftable/draft_test.rb +29 -0
  45. data/test/acts_as_draftable/rcrm_acts_as_draftable_test.rb +179 -0
  46. data/test/{acts_as_taggable_test.rb → acts_as_taggable/rcrm_acts_as_taggable_test.rb} +117 -156
  47. data/test/acts_as_taggable/tag_list_test.rb +34 -0
  48. data/test/acts_as_taggable/tag_test.rb +72 -0
  49. data/test/acts_as_taggable/tagging_test.rb +15 -0
  50. data/test/{viewed_test.rb → acts_as_viewed/rcrm_acts_as_viewed_test.rb} +17 -15
  51. data/test/acts_as_votable/rcrm_acts_as_votable_test.rb +19 -0
  52. data/test/acts_as_votable/rcrm_acts_as_voter_test.rb +14 -0
  53. data/test/{votable_model_test.rb → acts_as_votable/votable_test.rb} +34 -5
  54. data/test/{voter_model_test.rb → acts_as_votable/voter_test.rb} +8 -8
  55. data/test/currency_test.rb +10 -10
  56. data/test/database.yml +14 -14
  57. data/test/fixtures/issues.yml +13 -1
  58. data/test/fixtures/news.yml +8 -0
  59. data/test/fixtures/projects.yml +10 -0
  60. data/test/fixtures/users.yml +6 -2
  61. data/test/liquid/drops/issues_drop_test.rb +34 -0
  62. data/test/liquid/drops/news_drop_test.rb +38 -0
  63. data/test/liquid/drops/projects_drop_test.rb +44 -0
  64. data/test/liquid/drops/uses_drop_test.rb +36 -0
  65. data/test/liquid/filters/arrays_filter_test.rb +31 -0
  66. data/test/liquid/filters/base_filter_test.rb +63 -0
  67. data/test/liquid/filters/colors_filter_test.rb +33 -0
  68. data/test/liquid/liquid_helper.rb +34 -0
  69. data/test/models/issue.rb +14 -0
  70. data/test/models/news.rb +3 -0
  71. data/test/models/project.rb +8 -0
  72. data/test/{fixtures → models}/user.rb +5 -1
  73. data/test/{fixtures → models}/vote_classes.rb +0 -21
  74. data/test/money_helper_test.rb +5 -5
  75. data/test/schema.rb +33 -10
  76. data/test/test_helper.rb +20 -72
  77. data/vendor/assets/images/vcard.png +0 -0
  78. data/vendor/assets/javascripts/Chart.bundle.min.js +16 -0
  79. data/vendor/assets/javascripts/select2.js +3 -0
  80. data/vendor/assets/javascripts/select2_helpers.js +186 -0
  81. data/vendor/assets/stylesheets/select2.css +414 -0
  82. metadata +162 -38
  83. data/lib/redmine_crm/rcrm_acts_as_viewed.rb +0 -287
  84. data/lib/redmine_crm/rcrm_acts_as_voter.rb +0 -27
  85. data/lib/redmine_crm/tag.rb +0 -81
  86. data/lib/redmine_crm/tag_list.rb +0 -112
  87. data/lib/redmine_crm/tagging.rb +0 -20
  88. data/test/fixtures/issue.rb +0 -14
  89. data/test/tag_test.rb +0 -64
  90. data/test/tagging_test.rb +0 -14
  91. data/test/votable_test.rb +0 -17
@@ -0,0 +1,217 @@
1
+ require 'uri'
2
+ require 'rack'
3
+ require 'json'
4
+ require 'date'
5
+ require 'liquid'
6
+
7
+ module RedmineCrm
8
+ module Liquid
9
+ module Filters
10
+ module Base
11
+ include RedmineCrm::MoneyHelper
12
+
13
+ def textilize(input)
14
+ RedCloth3.new(input).to_html
15
+ end
16
+
17
+ def default(input, value)
18
+ input.blank? ? value : input
19
+ end
20
+
21
+ def underscore(input)
22
+ input.to_s.gsub(' ', '_').gsub('/', '_').underscore
23
+ end
24
+
25
+ def dasherize(input)
26
+ input.to_s.gsub(' ', '-').gsub('/', '-').dasherize
27
+ end
28
+
29
+ def shuffle(array)
30
+ array.to_a.shuffle
31
+ end
32
+
33
+ def random(input)
34
+ rand(input.to_i)
35
+ end
36
+
37
+ def md5(input)
38
+ Digest::MD5.hexdigest(input) unless input.blank?
39
+ end
40
+
41
+ # example:
42
+ # {{ "http:://www.example.com?key=hello world" | encode }}
43
+ #
44
+ # => http%3A%3A%2F%2Fwww.example.com%3Fkey%3Dhello+world
45
+ def encode(input)
46
+ ::Rack::Utils.escape(input)
47
+ end
48
+
49
+ # example:
50
+ # {{ today | plus_days: 2 }}
51
+ def plus_days(input, distanse)
52
+ return '' if input.nil?
53
+ days = distanse.to_i
54
+ input.to_date + days.days rescue 'Invalid date'
55
+ end
56
+
57
+ # example:
58
+ # {{ today | date_range: '2015-12-12' }}
59
+ def date_range(input, distanse)
60
+ return '' if input.nil?
61
+ (input.to_date - distanse.to_date).to_i rescue 'Invalid date'
62
+ end
63
+
64
+ # example:
65
+ # {{ now | utc }}
66
+ def utc(input)
67
+ return '' if input.nil?
68
+ input.to_time.utc rescue 'Invalid date'
69
+ end
70
+
71
+ def modulo(input, operand)
72
+ apply_operation(input, operand, :%)
73
+ end
74
+
75
+ def round(input, n = 0)
76
+ result = to_number(input).round(to_number(n))
77
+ result = result.to_f if result.is_a?(BigDecimal)
78
+ result = result.to_i if n == 0
79
+ result
80
+ end
81
+
82
+ def ceil(input)
83
+ to_number(input).ceil.to_i
84
+ end
85
+
86
+ def floor(input)
87
+ to_number(input).floor.to_i
88
+ end
89
+
90
+ def currency(input, currency_code = 'USD')
91
+ price_to_currency(input, currency_code, :converted => false)
92
+ end
93
+
94
+ def call_method(input, method_name)
95
+ if input.respond_to?(method_name)
96
+ input.method(method_name).call
97
+ end
98
+ end
99
+
100
+ def custom_field(input, field_name)
101
+ if input.respond_to?(:custom_field_values)
102
+ custom_value = input.custom_field_values.detect { |cfv| cfv.custom_field.name == field_name }
103
+ custom_value.custom_field.format.formatted_custom_value(nil, custom_value)
104
+ end
105
+ end
106
+
107
+ def custom_fields(input)
108
+ if input.respond_to?(:custom_field_values)
109
+ input.custom_field_values.map { |cfv| cfv.custom_field.name }
110
+ end
111
+ end
112
+
113
+ def attachment(input, file_name)
114
+ if input.respond_to?(:attachments)
115
+ if input.attachments.is_a?(Hash)
116
+ attachment = input.attachments[file_name]
117
+ else
118
+ attachment = input.attachments.detect{|a| a.file_name == file_name}
119
+ end
120
+ AttachmentDrop.new attachment if attachment
121
+ end
122
+ end
123
+
124
+ protected
125
+
126
+ # Convert an array of properties ('key:value') into a hash
127
+ # Ex: ['width:50', 'height:100'] => { :width => '50', :height => '100' }
128
+ def args_to_options(*args)
129
+ options = {}
130
+ args.flatten.each do |a|
131
+ if (a =~ /^(.*):(.*)$/)
132
+ options[$1.to_sym] = $2
133
+ end
134
+ end
135
+ options
136
+ end
137
+
138
+ # Write options (Hash) into a string according to the following pattern:
139
+ # <key1>="<value1>", <key2>="<value2", ...etc
140
+ def inline_options(options = {})
141
+ return '' if options.empty?
142
+ (options.stringify_keys.sort.to_a.collect { |a, b| "#{a}=\"#{b}\"" }).join(' ') << ' '
143
+ end
144
+
145
+ def sort_input(input, property, order)
146
+ input.sort do |apple, orange|
147
+ apple_property = item_property(apple, property)
148
+ orange_property = item_property(orange, property)
149
+
150
+ if !apple_property.nil? && orange_property.nil?
151
+ - order
152
+ elsif apple_property.nil? && !orange_property.nil?
153
+ + order
154
+ else
155
+ apple_property <=> orange_property
156
+ end
157
+ end
158
+ end
159
+
160
+ def time(input)
161
+ case input
162
+ when Time
163
+ input.clone
164
+ when Date
165
+ input.to_time
166
+ when String
167
+ Time.parse(input) rescue Time.at(input.to_i)
168
+ when Numeric
169
+ Time.at(input)
170
+ else
171
+ raise Errors::InvalidDateError,
172
+ "Invalid Date: '#{input.inspect}' is not a valid datetime."
173
+ end.localtime
174
+ end
175
+
176
+ def groupable?(element)
177
+ element.respond_to?(:group_by)
178
+ end
179
+
180
+ def item_property(item, property)
181
+ if item.respond_to?(:to_liquid)
182
+ property.to_s.split(".").reduce(item.to_liquid) do |subvalue, attribute|
183
+ subvalue[attribute]
184
+ end
185
+ elsif item.respond_to?(:data)
186
+ item.data[property.to_s]
187
+ else
188
+ item[property.to_s]
189
+ end
190
+ end
191
+
192
+ def as_liquid(item)
193
+ case item
194
+ when Hash
195
+ pairs = item.map { |k, v| as_liquid([k, v]) }
196
+ Hash[pairs]
197
+ when Array
198
+ item.map { |i| as_liquid(i) }
199
+ else
200
+ if item.respond_to?(:to_liquid)
201
+ liquidated = item.to_liquid
202
+ # prevent infinite recursion for simple types (which return `self`)
203
+ if liquidated == item
204
+ item
205
+ else
206
+ as_liquid(liquidated)
207
+ end
208
+ else
209
+ item
210
+ end
211
+ end
212
+ end
213
+ end
214
+ ::Liquid::Template.register_filter(RedmineCrm::Liquid::Filters::Base)
215
+ end
216
+ end
217
+ end
@@ -0,0 +1,31 @@
1
+ require 'liquid'
2
+
3
+ module RedmineCrm
4
+ module Liquid
5
+ module Filters
6
+ module Colors
7
+ def darken_color(input, value=0.4)
8
+ RedmineCrm::ColorsHelper.darken_color(input, value.to_f)
9
+ end
10
+
11
+ def lighten_color(input, value=0.6)
12
+ RedmineCrm::ColorsHelper.lighten_color(input, value.to_f)
13
+ end
14
+
15
+ def contrasting_text_color(input)
16
+ RedmineCrm::ColorsHelper.contrasting_text_color(input)
17
+ end
18
+
19
+ def hex_color(input)
20
+ RedmineCrm::ColorsHelper.hex_color(input)
21
+ end
22
+
23
+ def convert_to_brightness_value(input)
24
+ RedmineCrm::ColorsHelper.convert_to_brightness_value(input)
25
+ end
26
+
27
+ end
28
+ ::Liquid::Template.register_filter(RedmineCrm::Liquid::Filters::Colors)
29
+ end
30
+ end
31
+ end
@@ -1,5 +1,3 @@
1
- # byebug
2
- # require 'action_controller'
3
1
  require 'action_view'
4
2
 
5
3
  module RedmineCrm
@@ -41,9 +39,9 @@ module RedmineCrm
41
39
  end
42
40
 
43
41
  def all_currencies
44
- Currency.table.inject([]) do |array, (id, attributes)|
42
+ Currency.table.inject([]) do |array, (_, attributes)|
45
43
  array ||= []
46
- array << ["#{attributes[:name]}" + (attributes[:symbol].blank? ? "" : " (#{attributes[:symbol]})"), attributes[:iso_code]]
44
+ array << [attributes[:name].to_s + (attributes[:symbol].blank? ? '' : " (#{attributes[:symbol]})"), attributes[:iso_code]]
47
45
  array
48
46
  end.sort{|x, y| x[0] <=> y[0]}
49
47
  end
@@ -1,3 +1,3 @@
1
1
  module RedmineCrm
2
- VERSION = "0.0.23"
2
+ VERSION = '0.0.43'
3
3
  end
data/lib/redmine_crm.rb CHANGED
@@ -1,27 +1,62 @@
1
- require "redmine_crm/version"
2
-
3
- require "redmine_crm/tag"
4
- require "redmine_crm/tag_list"
5
- require "redmine_crm/tagging"
6
- require "redmine_crm/rcrm_acts_as_taggable"
7
- require "redmine_crm/helpers/tags_helper"
8
- require "redmine_crm/currency"
9
- require "redmine_crm/money_helper"
10
- require "redmine_crm/rcrm_acts_as_votable"
11
- require "redmine_crm/rcrm_acts_as_voter"
12
- require "redmine_crm/vote"
13
- require "redmine_crm/voter"
14
- require "redmine_crm/rcrm_acts_as_viewed"
1
+ require 'active_record'
2
+ require 'action_view'
3
+
4
+ require 'redmine_crm/version'
5
+
6
+ require 'redmine_crm/acts_as_list/list'
7
+ require 'redmine_crm/acts_as_taggable/tag'
8
+ require 'redmine_crm/acts_as_taggable/tag_list'
9
+ require 'redmine_crm/acts_as_taggable/tagging'
10
+ require 'redmine_crm/acts_as_taggable/rcrm_acts_as_taggable'
11
+ require 'redmine_crm/acts_as_viewed/rcrm_acts_as_viewed'
12
+ require 'redmine_crm/acts_as_votable/rcrm_acts_as_votable'
13
+ require 'redmine_crm/acts_as_votable/rcrm_acts_as_voter'
14
+ require 'redmine_crm/acts_as_votable/vote'
15
+ require 'redmine_crm/acts_as_votable/voter'
16
+ require 'redmine_crm/acts_as_draftable/rcrm_acts_as_draftable'
17
+ require 'redmine_crm/acts_as_draftable/draft'
18
+
19
+ require 'redmine_crm/currency'
20
+ require 'redmine_crm/helpers/tags_helper'
21
+ require 'redmine_crm/money_helper'
22
+ require 'redmine_crm/colors_helper'
23
+
24
+ require 'liquid'
25
+ require 'redmine_crm/liquid/filters/base'
26
+ require 'redmine_crm/liquid/filters/arrays'
27
+ require 'redmine_crm/liquid/filters/colors'
28
+ require 'redmine_crm/liquid/drops/issues_drop'
29
+ require 'redmine_crm/liquid/drops/news_drop'
30
+ require 'redmine_crm/liquid/drops/projects_drop'
31
+ require 'redmine_crm/liquid/drops/users_drop'
32
+ require 'redmine_crm/liquid/drops/time_entries_drop'
33
+
34
+ require 'redmine_crm/helpers/external_assets_helper'
35
+ require 'redmine_crm/helpers/form_tag_helper'
36
+ require 'redmine_crm/assets_manager'
37
+
38
+ require 'redmine_crm/compatibility/application_controller_patch'
39
+
40
+ module RedmineCrm
41
+ GEM_NAME = 'redmine_crm'.freeze
42
+ end
15
43
 
16
44
  if defined?(ActiveRecord::Base)
17
- ActiveRecord::Base.extend(RedmineCrm::ActsAsVotable::Votable)
45
+ ActiveRecord::Base.send :include, RedmineCrm::ActsAsList::List
18
46
  ActiveRecord::Base.extend(RedmineCrm::ActsAsVotable::Voter)
47
+ ActiveRecord::Base.extend(RedmineCrm::ActsAsVotable::Votable)
19
48
  end
20
49
 
21
- def requires_redmine_crm(arg)
50
+ RedmineCrm::AssetsManager.install_assets
22
51
 
52
+ if defined?(ActionView::Base)
53
+ ActionView::Base.send :include, RedmineCrm::ExternalAssetsHelper
54
+ ActionView::Base.send :include, RedmineCrm::FormTagHelper
55
+ end
56
+
57
+ def requires_redmine_crm(arg)
23
58
  def compare_versions(requirement, current)
24
- raise ArgumentError.new("wrong version format") unless check_version_format(requirement)
59
+ raise ArgumentError.new('wrong version format') unless check_version_format(requirement)
25
60
  requirement = requirement.split('.').collect(&:to_i)
26
61
  requirement <=> current.slice(0, requirement.size)
27
62
  end
@@ -33,11 +68,11 @@ def requires_redmine_crm(arg)
33
68
  arg = { :version_or_higher => arg } unless arg.is_a?(Hash)
34
69
  arg.assert_valid_keys(:version, :version_or_higher)
35
70
 
36
- current = RedmineCrm::VERSION.split(".").map{|x| x.to_i}
71
+ current = RedmineCrm::VERSION.split('.').map { |x| x.to_i }
37
72
  arg.each do |k, req|
38
73
  case k
39
74
  when :version_or_higher
40
- raise ArgumentError.new(":version_or_higher accepts a version string only") unless req.is_a?(String)
75
+ raise ArgumentError.new(':version_or_higher accepts a version string only') unless req.is_a?(String)
41
76
  unless compare_versions(req, current) <= 0
42
77
  Rails.logger.error "\033[31m[ERROR]\033[0m Redmine requires redmine_crm gem version #{req} or higher (you're using #{RedmineCrm::VERSION}).\n\033[31m[ERROR]\033[0m Please update with 'bundle update redmine_crm'." if Rails.logger
43
78
  abort "\033[31mRedmine requires redmine_crm gem version #{req} or higher (you're using #{RedmineCrm::VERSION}).\nPlease update with 'bundle update redmine_crm'.\033[0m"
@@ -53,9 +88,9 @@ def requires_redmine_crm(arg)
53
88
  abort "\033[31mRedmine requires redmine_crm gem version between #{req.first} and #{req.last} (you're using #{RedmineCrm::VERSION}).\nPlease update with 'bundle update redmine_crm'.\033[0m"
54
89
  end
55
90
  else
56
- raise ArgumentError.new(":version option accepts a version string, an array or a range of versions")
91
+ raise ArgumentError.new(':version option accepts a version string, an array or a range of versions')
57
92
  end
58
93
  end
59
94
  end
60
95
  true
61
- end
96
+ end
data/redmine_crm.gemspec CHANGED
@@ -6,10 +6,10 @@ require 'redmine_crm/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "redmine_crm"
8
8
  spec.version = RedmineCrm::VERSION
9
- spec.authors = ["RedmineCRM"]
9
+ spec.authors = ["RedmineUP"]
10
10
  spec.email = ["support@redminecrm.com"]
11
- spec.summary = %q{Common libraries for RedmineCRM plugins for Redmine}
12
- spec.description = %q{Common libraries for RedmineCRM plugins for Redmine. Requered Redmine from http://redmine.org}
11
+ spec.summary = %q{Common libraries for RedmineUP plugins for Redmine}
12
+ spec.description = %q{Common libraries for RedmineUP plugins (www.redmineup.com) for Redmine. Requered Redmine from http://redmine.org}
13
13
  spec.homepage = ""
14
14
  spec.license = "GPL2"
15
15
 
@@ -18,5 +18,10 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- end
21
+ spec.add_runtime_dependency 'rails'
22
+ spec.add_runtime_dependency 'liquid', '< 2.6.4'
22
23
 
24
+ spec.add_development_dependency 'sqlite3'
25
+ spec.add_development_dependency 'mysql2'
26
+ spec.add_development_dependency 'pg'
27
+ end
@@ -0,0 +1,29 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ class DraftTest < ActiveSupport::TestCase
4
+ def test_restore
5
+ issue = Issue.new(subject: 'some subject', description: 'some description')
6
+
7
+ issue.save_draft
8
+ restored_issue = RedmineCrm::ActsAsDraftable::Draft.find(issue.draft_id).restore
9
+
10
+ assert_equal issue.subject, restored_issue.subject
11
+ assert_equal issue.description, restored_issue.description
12
+ end
13
+
14
+ def test_restore_all
15
+ first_issue = Issue.new(subject: 'first subject')
16
+ first_issue.save_draft
17
+ second_issue = Issue.new(subject: 'second subject')
18
+ second_issue.save_draft
19
+
20
+ restored_issues = RedmineCrm::ActsAsDraftable::Draft.restore_all
21
+ assert_equal [first_issue.subject, second_issue.subject], restored_issues.map(&:subject).sort
22
+ end
23
+
24
+ private
25
+
26
+ def current_user
27
+ users(:sam)
28
+ end
29
+ end
@@ -0,0 +1,179 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ class RcrmActsAsDraftableTest < ActiveSupport::TestCase
4
+ def test_rcrm_acts_as_draftable_without_arguments
5
+ assert_nothing_raised do
6
+ Project.rcrm_acts_as_draftable
7
+ end
8
+ end
9
+
10
+ class SomeClass < ActiveRecord::Base; end
11
+ def test_rcrm_acts_as_draftable_with_parent
12
+ assert_nothing_raised do
13
+ News.rcrm_acts_as_draftable(parent: :author)
14
+ end
15
+ assert User.new.respond_to?(:drafts)
16
+ end
17
+
18
+ def test_rcrm_acts_as_draftable_with_non_existing_parent
19
+ assert_raises do
20
+ Issue.rcrm_acts_as_draftable(parent: :foo)
21
+ end
22
+ end
23
+
24
+ def test_rcrm_acts_as_draftable_with_non_hash_argument
25
+ assert_raises do
26
+ Issue.rcrm_acts_as_draftable('bar')
27
+ end
28
+ end
29
+
30
+ def test_rcrm_acts_as_draftable_with_invalid_hash_key
31
+ assert_raises do
32
+ Issue.rcrm_acts_as_draftable(baz: 'qux')
33
+ end
34
+ end
35
+
36
+ def test_drafts
37
+ Issue.rcrm_acts_as_draftable parent: :project
38
+ issue = Issue.new
39
+ issue.save_draft
40
+
41
+ assert_equal 1, Issue.drafts(current_user).count
42
+ assert_equal RedmineCrm::ActsAsDraftable::Draft, Issue.drafts(current_user).first.class
43
+ end
44
+
45
+ def test_from_draft
46
+ Issue.rcrm_acts_as_draftable parent: :project
47
+ issue = Issue.new(subject: 'subject')
48
+ issue.save_draft
49
+
50
+ issue_from_draft = Issue.from_draft(issue.draft_id)
51
+
52
+ assert_equal Issue, issue_from_draft.class
53
+ assert_equal true, issue_from_draft.new_record?
54
+ assert_equal issue.draft_id, issue_from_draft.draft_id
55
+
56
+ assert_equal issue.subject, issue_from_draft.subject
57
+ end
58
+
59
+ def test_draft_deleted_after_save
60
+ issue = Issue.new(subject: 'subject')
61
+ issue.save_draft
62
+
63
+ issue_from_draft = Issue.from_draft(issue.draft_id)
64
+
65
+ assert_difference 'Issue.count' do
66
+ assert_difference 'RedmineCrm::ActsAsDraftable::Draft.count', -1 do
67
+ issue_from_draft.save!
68
+ end
69
+ end
70
+ assert_nil issue_from_draft.draft_id
71
+ end
72
+
73
+ def test_from_draft_with_non_existing_draft_id
74
+ assert_raises do
75
+ Issue.from_draft(999)
76
+ end
77
+ end
78
+
79
+ def test_from_draft_with_wrong_type
80
+ Project.rcrm_acts_as_draftable
81
+
82
+ project = Project.new
83
+ project.save_draft
84
+
85
+ assert_raises do
86
+ Issue.from_draft(project.draft_id)
87
+ end
88
+ end
89
+
90
+ def test_dump_to_draft
91
+ assert_equal String, Issue.new.dump_to_draft.class
92
+ end
93
+
94
+ def test_load_from_draft
95
+ attributes = {subject: 'subject', description: 'description'}
96
+ draft = Issue.new(attributes).dump_to_draft
97
+
98
+ issue = Issue.new
99
+ issue.load_from_draft(draft)
100
+
101
+ assert_equal attributes[:subject], issue.subject
102
+ assert_equal attributes[:description], issue.description
103
+ end
104
+
105
+ def test_save_draft
106
+ Issue.rcrm_acts_as_draftable parent: :project
107
+ attributes = { subject: 'subject' }
108
+ issue = Issue.new(attributes)
109
+
110
+ assert_no_difference 'Issue.count' do
111
+ assert_difference 'RedmineCrm::ActsAsDraftable::Draft.count' do
112
+ result = issue.save_draft
113
+ assert_equal true, result
114
+ end
115
+ end
116
+ assert_not_nil issue.draft_id
117
+
118
+ draft = RedmineCrm::ActsAsDraftable::Draft.find(issue.draft_id)
119
+ assert_equal 'Issue', draft.target_type
120
+ assert_equal current_user.id, draft.user_id
121
+ assert_equal attributes[:subject], draft.restore.subject
122
+ end
123
+
124
+ def test_save_draft_with_associations
125
+ Issue.rcrm_acts_as_draftable parent: :project
126
+ issue = Issue.new(project: projects(:second_project))
127
+ issue.save_draft
128
+
129
+ draft = RedmineCrm::ActsAsDraftable::Draft.find(issue.draft_id)
130
+ assert_equal issue.project.name, draft.restore.project.name
131
+ end
132
+
133
+ def test_save_draft_updates_existing_draft
134
+ Issue.rcrm_acts_as_draftable parent: :project
135
+ issue = Issue.new
136
+ issue.save_draft
137
+
138
+ issue.subject = 'changed subject'
139
+ assert_no_difference 'Issue.count' do
140
+ assert_no_difference 'RedmineCrm::ActsAsDraftable::Draft.count' do
141
+ issue.save_draft
142
+ end
143
+ end
144
+
145
+ draft = RedmineCrm::ActsAsDraftable::Draft.find(issue.draft_id)
146
+ assert_equal issue.subject, draft.restore.subject
147
+ end
148
+
149
+ def test_save_draft_does_not_save_persisted_object
150
+ issue = issues(:second_issue)
151
+ assert_equal false, issue.save_draft
152
+ end
153
+
154
+ def test_save_draft_saves_persisted_but_changed_object
155
+ issue = issues(:second_issue)
156
+ issue.subject = 'changed subject'
157
+ assert_equal true, issue.save_draft
158
+ end
159
+
160
+ def test_update_draft
161
+ issue = Issue.new(subject: 'subject')
162
+ issue.save_draft
163
+
164
+ assert_no_difference 'Issue.count' do
165
+ assert_no_difference 'RedmineCrm::ActsAsDraftable::Draft.count' do
166
+ issue.update_draft(subject: 'updated_subject')
167
+ end
168
+ end
169
+
170
+ draft = RedmineCrm::ActsAsDraftable::Draft.find(issue.draft_id)
171
+ assert_equal issue.subject, draft.restore.subject
172
+ end
173
+
174
+ private
175
+
176
+ def current_user
177
+ users(:sam)
178
+ end
179
+ end