redmine_crm 0.0.4

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.
@@ -0,0 +1,82 @@
1
+ module RedmineCrm
2
+ class Tag < ActiveRecord::Base
3
+ has_many :taggings, :dependent => :destroy
4
+
5
+ validates_presence_of :name
6
+ # validates_uniqueness_of :name
7
+ validates :name, :uniqueness => true
8
+ validates :name, :presence => true
9
+ cattr_accessor :destroy_unused
10
+ self.destroy_unused = false
11
+
12
+ attr_accessible :name if defined?(ActiveModel::MassAssignmentSecurity)
13
+
14
+ # LIKE is used for cross-database case-insensitivity
15
+ def self.find_or_create_with_like_by_name(name)
16
+ # find(:first, :conditions => ["name LIKE ?", name]) || create(:name => name)
17
+ where("name LIKE LOWER(?)", name.downcase).first || create(:name => name)
18
+ end
19
+
20
+ def ==(object)
21
+ super || (object.is_a?(Tag) && name == object.name)
22
+ end
23
+
24
+ def to_s
25
+ name
26
+ end
27
+
28
+ def count
29
+ read_attribute(:count).to_i
30
+ end
31
+
32
+ class << self
33
+ # Calculate the tag counts for all tags.
34
+ # :start_at - Restrict the tags to those created after a certain time
35
+ # :end_at - Restrict the tags to those created before a certain time
36
+ # :conditions - A piece of SQL conditions to add to the query
37
+ # :limit - The maximum number of tags to return
38
+ # :order - A piece of SQL to order by. Eg 'count desc' or 'taggings.created_at desc'
39
+ # :at_least - Exclude tags with a frequency less than the given value
40
+ # :at_most - Exclude tags with a frequency greater than the given value
41
+ def counts(options = {})
42
+ # find(:all, options_for_counts(options))
43
+ opt = options_for_counts(options)
44
+ # byebug
45
+ select(opt[:select]).where(opt[:conditions]).joins(opt[:joins]).group(opt[:group])
46
+ end
47
+
48
+ def options_for_counts(options = {})
49
+ options.assert_valid_keys :start_at, :end_at, :conditions, :at_least, :at_most, :order, :limit, :joins
50
+ options = options.dup
51
+
52
+ start_at = sanitize_sql(["#{Tagging.table_name}.created_at >= ?", options.delete(:start_at)]) if options[:start_at]
53
+ end_at = sanitize_sql(["#{Tagging.table_name}.created_at <= ?", options.delete(:end_at)]) if options[:end_at]
54
+
55
+ conditions = [
56
+ (sanitize_sql(options.delete(:conditions)) if options[:conditions]),
57
+ start_at,
58
+ end_at
59
+ ].compact
60
+
61
+ conditions = conditions.join(' AND ') if conditions.any?
62
+
63
+ joins = ["INNER JOIN #{Tagging.table_name} ON #{Tag.table_name}.id = #{Tagging.table_name}.tag_id"]
64
+ joins << options.delete(:joins) if options[:joins]
65
+
66
+ at_least = sanitize_sql(['COUNT(*) >= ?', options.delete(:at_least)]) if options[:at_least]
67
+ at_most = sanitize_sql(['COUNT(*) <= ?', options.delete(:at_most)]) if options[:at_most]
68
+ having = "COUNT(*) > 0"
69
+ having = [having, at_least, at_most].compact.join(' AND ')
70
+ group_by = "#{Tag.table_name}.id, #{Tag.table_name}.name"
71
+ # group_by << " AND #{having}" unless having.blank?
72
+
73
+ { :select => "#{Tag.table_name}.id, #{Tag.table_name}.name, COUNT(*) AS count",
74
+ :joins => joins.join(" "),
75
+ :conditions => conditions,
76
+ :group => group_by,
77
+ :having => having
78
+ }.update(options)
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,112 @@
1
+ module RedmineCrm
2
+ class TagList < Array
3
+ cattr_accessor :delimiter
4
+ self.delimiter = ','
5
+
6
+ def initialize(*args)
7
+ add(*args)
8
+ end
9
+
10
+ # Add tags to the tag_list. Duplicate or blank tags will be ignored.
11
+ #
12
+ # tag_list.add("Fun", "Happy")
13
+ #
14
+ # Use the <tt>:parse</tt> option to add an unparsed tag string.
15
+ #
16
+ # tag_list.add("Fun, Happy", :parse => true)
17
+ def add(*names)
18
+ extract_and_apply_options!(names)
19
+ concat(names)
20
+ clean!
21
+ self
22
+ end
23
+
24
+ # Remove specific tags from the tag_list.
25
+ #
26
+ # tag_list.remove("Sad", "Lonely")
27
+ #
28
+ # Like #add, the <tt>:parse</tt> option can be used to remove multiple tags in a string.
29
+ #
30
+ # tag_list.remove("Sad, Lonely", :parse => true)
31
+ def remove(*names)
32
+ extract_and_apply_options!(names)
33
+ delete_if { |name| names.include?(name) }
34
+ self
35
+ end
36
+
37
+ # Toggle the presence of the given tags.
38
+ # If a tag is already in the list it is removed, otherwise it is added.
39
+ def toggle(*names)
40
+ extract_and_apply_options!(names)
41
+
42
+ names.each do |name|
43
+ include?(name) ? delete(name) : push(name)
44
+ end
45
+
46
+ clean!
47
+ self
48
+ end
49
+
50
+ # Transform the tag_list into a tag string suitable for edting in a form.
51
+ # The tags are joined with <tt>TagList.delimiter</tt> and quoted if necessary.
52
+ #
53
+ # tag_list = TagList.new("Round", "Square,Cube")
54
+ # tag_list.to_s # 'Round, "Square,Cube"'
55
+ def to_s
56
+ clean!
57
+
58
+ map do |name|
59
+ name.include?(delimiter) ? "\"#{name}\"" : name
60
+ end.join(delimiter.ends_with?(" ") ? delimiter : "#{delimiter} ")
61
+ end
62
+
63
+ private
64
+ # Remove whitespace, duplicates, and blanks.
65
+ def clean!
66
+ reject!(&:blank?)
67
+ map!(&:strip)
68
+ uniq!
69
+ end
70
+
71
+ def extract_and_apply_options!(args)
72
+ options = args.last.is_a?(Hash) ? args.pop : {}
73
+ options.assert_valid_keys :parse
74
+
75
+ if options[:parse]
76
+ args.map! { |a| self.class.from(a) }
77
+ end
78
+
79
+ args.flatten!
80
+ end
81
+
82
+ class << self
83
+ # Returns a new TagList using the given tag string.
84
+ #
85
+ # tag_list = TagList.from("One , Two, Three")
86
+ # tag_list # ["One", "Two", "Three"]
87
+ def from(source)
88
+ tag_list = new
89
+
90
+ case source
91
+ when Array
92
+ tag_list.add(source)
93
+ else
94
+ string = source.to_s.dup
95
+
96
+ # Parse the quoted tags
97
+ [
98
+ /\s*#{delimiter}\s*(['"])(.*?)\1\s*/,
99
+ /^\s*(['"])(.*?)\1\s*#{delimiter}?/
100
+ ].each do |re|
101
+ string.gsub!(re) { tag_list << $2; "" }
102
+ end
103
+
104
+ tag_list.add(string.split(delimiter))
105
+ end
106
+
107
+ tag_list
108
+ end
109
+ end
110
+ end
111
+
112
+ end
@@ -0,0 +1,20 @@
1
+ module RedmineCrm
2
+
3
+ class Tagging < ActiveRecord::Base #:nodoc:
4
+ belongs_to :tag
5
+ belongs_to :taggable, :polymorphic => true
6
+
7
+ after_destroy :destroy_tag_if_unused
8
+
9
+ private
10
+
11
+ def destroy_tag_if_unused
12
+ if Tag.destroy_unused
13
+ if tag.taggings.count.zero?
14
+ tag.destroy
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,15 @@
1
+ module RedmineCrm
2
+ module TagsHelper
3
+ # See the README for an example using tag_cloud.
4
+ def tag_cloud(tags, classes)
5
+ return if tags.empty?
6
+
7
+ max_count = tags.sort_by(&:count).last.count.to_f
8
+
9
+ tags.each do |tag|
10
+ index = ((tag.count / max_count) * (classes.size - 1)).round
11
+ yield tag, classes[index]
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ module RedmineCrm
2
+ VERSION = "0.0.4"
3
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'redmine_crm/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "redmine_crm"
8
+ spec.version = RedmineCrm::VERSION
9
+ spec.authors = ["RedmineCRM"]
10
+ spec.email = ["support@redminecrm.com"]
11
+ spec.summary = %q{plugins for remine}
12
+ spec.description = %q{plugins for Redmine}
13
+ spec.homepage = ""
14
+ spec.license = "GPL2"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "minitest"
24
+ spec.add_development_dependency "activerecord"
25
+ spec.add_development_dependency "actionpack"
26
+ spec.add_development_dependency "sqlite3"
27
+ spec.add_development_dependency "mysql2"
28
+ spec.add_development_dependency "activerecord-mysql-adapter"
29
+ spec.add_development_dependency "pg"
30
+ end
@@ -0,0 +1,384 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class ActsAsTaggableTest < ActiveSupport::TestCase
4
+ def test_find_related_tags_with
5
+ assert_equivalent [tags(:feature), tags(:bug), tags(:question)], Issue.find_related_tags("error")
6
+ assert_equivalent [tags(:feature), tags(:error), tags(:question)], Issue.find_related_tags(tags(:bug))
7
+ assert_equivalent [tags(:error), tags(:question)], Issue.find_related_tags(["New feature", "bug"])
8
+ assert_equivalent [tags(:feature), tags(:bug)], Issue.find_related_tags([tags(:error), tags(:question)])
9
+ end
10
+
11
+ def test_find_tagged_with_include_and_order
12
+ assert_equal issues(:third_issue, :first_issue, :second_issue), Issue.find_tagged_with("question", :order => "issues.description DESC", :include => :user).to_a
13
+ end
14
+
15
+ def test_find_related_tags_with_non_existent_tags
16
+ assert_equal [], Issue.find_related_tags("ABCDEFG")
17
+ assert_equal [], Issue.find_related_tags(['HIJKLM'])
18
+ end
19
+
20
+ def test_find_related_tags_with_nothing
21
+ assert_equal [], Issue.find_related_tags("")
22
+ assert_equal [], Issue.find_related_tags([])
23
+ end
24
+
25
+ def test_find_tagged_with
26
+ assert_equivalent [issues(:first_issue), issues(:second_issue), issues(:third_issue)], Issue.find_tagged_with('"error"')
27
+ assert_equal Issue.find_tagged_with('"error"'), Issue.find_tagged_with(['error'])
28
+ assert_equal Issue.find_tagged_with('"error"'), Issue.find_tagged_with([tags(:error)])
29
+
30
+ assert_equivalent [issues(:second_issue),], Issue.find_tagged_with('New feature')
31
+ assert_equal Issue.find_tagged_with('New feature'), Issue.find_tagged_with(['New feature'])
32
+ assert_equal Issue.find_tagged_with('New feature'), Issue.find_tagged_with([tags(:feature)])
33
+
34
+ # assert_equivalent [issues(:jonathan_bad_cat), issues(:jonathan_dog), issues(:second_issue)], Issue.find_tagged_with('"Crazy animal" Bad')
35
+ # assert_equal Issue.find_tagged_with('"Crazy animal" Bad'), Issue.find_tagged_with(['Crazy animal', 'Bad'])
36
+ # assert_equal Issue.find_tagged_with('"Crazy animal" Bad'), Issue.find_tagged_with([tags(:animal), tags(:bad)])
37
+ end
38
+
39
+ def test_find_tagged_with_nothing
40
+ assert_equal [], Issue.find_tagged_with("")
41
+ assert_equal [], Issue.find_tagged_with([])
42
+ end
43
+
44
+ def test_find_tagged_with_nonexistant_tags
45
+ assert_equal [], Issue.find_tagged_with('ABCDEFG')
46
+ assert_equal [], Issue.find_tagged_with(['HIJKLM'])
47
+ assert_equal [], Issue.find_tagged_with([RedmineCrm::Tag.new(:name => 'unsaved tag')])
48
+ end
49
+
50
+ def test_find_tagged_with_match_all
51
+ assert_equivalent [issues(:second_issue)],
52
+ Issue.find_tagged_with('error, "bug", "New feature", "question"', :match_all => true)
53
+ end
54
+
55
+ def test_find_tagged_with_match_all_and_include
56
+ assert_equivalent [issues(:first_issue), issues(:second_issue), issues(:third_issue)], Issue.find_tagged_with(['error', 'question'], :match_all => true, :include => :tags)
57
+ end
58
+
59
+ def test_find_tagged_with_conditions
60
+ assert_equal [], Issue.find_tagged_with('"error", bug', :conditions => '1=0')
61
+ end
62
+
63
+ def test_find_tagged_with_duplicates_options_hash
64
+ options = { :conditions => '1=1' }.freeze
65
+ assert_nothing_raised { Issue.find_tagged_with("error", options) }
66
+ end
67
+
68
+ def test_find_tagged_with_exclusions
69
+ assert_equivalent [issues(:first_issue), issues(:third_issue)], Issue.find_tagged_with("bug", :exclude => true)
70
+ assert_equivalent [issues(:first_issue), issues(:third_issue)], Issue.find_tagged_with("'bug', feature", :exclude => true)
71
+ end
72
+
73
+ def test_find_options_for_find_tagged_with_no_tags_returns_empty_hash
74
+ assert_equal Hash.new, Issue.find_options_for_find_tagged_with("")
75
+ assert_equal Hash.new, Issue.find_options_for_find_tagged_with([nil])
76
+ end
77
+
78
+ def test_find_options_for_find_tagged_with_leaves_arguments_unchanged
79
+ original_tags = issues(:second_issue).tags.dup
80
+ Issue.find_options_for_find_tagged_with(issues(:second_issue).tags)
81
+ assert_equal original_tags, issues(:second_issue).tags
82
+ end
83
+
84
+ def test_find_options_for_find_tagged_with_respects_custom_table_name
85
+ RedmineCrm::Tagging.table_name = "categorisations"
86
+ RedmineCrm::Tag.table_name = "categories"
87
+
88
+ options = Issue.find_options_for_find_tagged_with("Hello")
89
+
90
+ assert_no_match(/ taggings /, options[:joins])
91
+ assert_no_match(/ tags /, options[:joins])
92
+
93
+ assert_match(/ categorisations /, options[:joins])
94
+ assert_match(/ categories /, options[:joins])
95
+ ensure
96
+ RedmineCrm::Tagging.table_name = "taggings"
97
+ RedmineCrm::Tag.table_name = "tags"
98
+ end
99
+
100
+ def test_include_tags_on_find_tagged_with
101
+ assert_nothing_raised do
102
+ Issue.find_tagged_with('error', :include => :tags)
103
+ Issue.find_tagged_with("error", :include => { :taggings => :tag })
104
+ end
105
+ end
106
+
107
+ def test_basic_tag_counts_on_class
108
+ assert_tag_counts Issue.tag_counts, :error => 3, :feature => 1, :question => 3, :bug => 1
109
+ # assert_tag_counts Issue.tag_counts, :good => 1, :question => 3, :question => 1, :bad => 1, :animal => 3
110
+ end
111
+
112
+ def test_tag_counts_on_class_with_date_conditions
113
+ assert_tag_counts Issue.tag_counts(:start_at => Date.new(2015, 1, 1)), :error => 2, :feature => 1, :question => 3, :bug => 1
114
+ assert_tag_counts Issue.tag_counts(:end_at => Date.new(2014, 12, 31)), :error => 1
115
+ assert_tag_counts Issue.tag_counts(:start_at => Date.new(2015, 1, 31), :end_at => Date.new(2015, 3, 1)), :question => 1
116
+
117
+ # assert_tag_counts Issue.tag_counts(:start_at => Date.new(2006, 8, 12), :end_at => Date.new(2006, 8, 19)), :good => 1, :question => 2, :bad => 1, :question => 1, :animal => 3
118
+ end
119
+
120
+ def test_tag_counts_on_class_with_frequencies
121
+ assert_tag_counts Issue.tag_counts(:at_least => 2), :question => 3, :error => 3
122
+ assert_tag_counts Issue.tag_counts(:at_most => 2), :bug => 1, :feature => 1
123
+ end
124
+
125
+ def test_tag_counts_on_class_with_frequencies_and_conditions
126
+ assert_tag_counts Issue.tag_counts(:at_least => 2, :conditions => '1=1'), :question => 3, :error => 3
127
+ end
128
+
129
+ def test_tag_counts_duplicates_options_hash
130
+ options = { :at_least => 2, :conditions => '1=1' }.freeze
131
+ assert_nothing_raised { Issue.tag_counts(options) }
132
+ end
133
+
134
+ def test_tag_counts_with_limit
135
+ assert_equal 2, Issue.tag_counts(:limit => 2).to_a.size
136
+ assert_equal 2, Issue.tag_counts(:at_least => 3, :limit => 2).to_a.size
137
+ end
138
+
139
+ def test_tag_counts_with_limit_and_order
140
+ assert_equivalent RedmineCrm::Tag.where(:id => [tags(:error), tags(:question)]), Issue.tag_counts(:order => 'count desc', :limit => 2)
141
+ end
142
+
143
+ def test_tag_counts_on_association
144
+ assert_tag_counts users(:jonathan).issues.tag_counts, :error => 2, :bug => 1, :question => 2, :feature => 1
145
+ assert_tag_counts users(:sam).issues.tag_counts, :error => 1, :question => 1
146
+
147
+ # assert_tag_counts users(:jonathan).issues.tag_counts, :animal => 3, :question => 1, :question => 1, :bad => 1
148
+ # assert_tag_counts users(:sam).issues.tag_counts, :question => 2, :good => 1
149
+ end
150
+
151
+ def test_tag_counts_on_association_with_options
152
+ assert_equal [], users(:jonathan).issues.tag_counts(:conditions => '1=0')
153
+ assert_tag_counts users(:jonathan).issues.tag_counts(:at_most => 2), :bug => 1,
154
+ :feature => 1, :error => 2, :question => 2
155
+ end
156
+
157
+ # def test_tag_counts_on_has_many_through
158
+ # assert_tag_counts users(:jonathan).magazines.tag_counts, :good => 1
159
+ # end
160
+
161
+ def test_tag_counts_on_model_instance
162
+ assert_tag_counts issues(:third_issue).tag_counts, :error => 3, :question => 3
163
+ end
164
+
165
+ def test_tag_counts_on_model_instance_merges_conditions
166
+ assert_tag_counts issues(:first_issue).tag_counts(:conditions => "tags.name = 'error'"), :error => 3
167
+ end
168
+
169
+ def test_tag_counts_on_model_instance_with_no_tags
170
+ issue = Issue.create!(:description => "desc")
171
+
172
+ assert_tag_counts issue.tag_counts, {}
173
+ end
174
+
175
+ def test_tag_counts_should_sanitize_scope_conditions
176
+ Issue.send :where, { "tags.id = ?" => tags(:error).id } do
177
+ assert_tag_counts Issue.tag_counts, :error => 3
178
+ end
179
+ end
180
+
181
+ def test_tag_counts_respects_custom_table_names
182
+ RedmineCrm::Tagging.table_name = "categorisations"
183
+ RedmineCrm::Tag.table_name = "categories"
184
+
185
+ options = Issue.find_options_for_tag_counts(:start_at => 2.weeks.ago, :end_at => Date.today)
186
+ sql = options.values.join(' ')
187
+
188
+ assert_no_match /taggings/, sql
189
+ assert_no_match /tags/, sql
190
+
191
+ assert_match /categorisations/, sql
192
+ assert_match /categories/, sql
193
+ ensure
194
+ RedmineCrm::Tagging.table_name = "taggings"
195
+ RedmineCrm::Tag.table_name = "tags"
196
+ end
197
+
198
+ def test_tag_list_reader
199
+ assert_equivalent ["error", "question"], issues(:first_issue).tag_list
200
+ assert_equivalent ["error", "New feature", "bug", "question"], issues(:second_issue).tag_list
201
+ end
202
+
203
+ def test_reassign_tag_list
204
+ assert_equivalent ["error", "question"], issues(:first_issue).tag_list
205
+ issues(:first_issue).taggings.reload
206
+
207
+ # Only an update of the issues table should be executed, the other two queries are for savepoints
208
+ # assert_queries 3 do
209
+ # issues(:first_issue).update_attributes!(:description => "new name", :tag_list => issues(:first_issue).tag_list.to_s)
210
+ # end
211
+
212
+ assert_equivalent ["error", "question"], issues(:first_issue).tag_list
213
+ end
214
+
215
+ def test_new_tags
216
+ assert_equivalent ["error", "question"], issues(:first_issue).tag_list
217
+ issues(:first_issue).update_attributes!(:tag_list => "#{issues(:first_issue).tag_list}, One, Two")
218
+ assert_equivalent ["error", "question", "One", "Two"], issues(:first_issue).tag_list
219
+ end
220
+
221
+ def test_remove_tag
222
+ assert_equivalent ["error", "question"], issues(:first_issue).tag_list
223
+ issues(:first_issue).update_attributes!(:tag_list => "error")
224
+ assert_equivalent ["error"], issues(:first_issue).tag_list
225
+ end
226
+
227
+ # def test_change_case_of_tags
228
+ # original_tag_names = issues(:second_issue).tag_list
229
+ # issues(:second_issue).update_attributes!(:tag_list => issues(:second_issue).tag_list.to_s.upcase)
230
+
231
+ # # The new tag list is not uppercase becuase the AR finders are not case-sensitive
232
+ # # and find the old tags when re-tagging with the uppercase tags.
233
+ # assert_equivalent original_tag_names, issues(:second_issue).reload.tag_list
234
+ # end
235
+
236
+ def test_remove_and_add_tag
237
+ assert_equivalent ["error", "question"], issues(:first_issue).tag_list
238
+ issues(:first_issue).update_attributes!(:tag_list => "question, Beautiful")
239
+ assert_equivalent ["question", "Beautiful"], issues(:first_issue).tag_list
240
+ end
241
+
242
+ def test_tags_not_saved_if_validation_fails
243
+ assert_equivalent ["error", "question"], issues(:first_issue).tag_list
244
+ assert !issues(:first_issue).update_attributes(:tag_list => "One, Two", :description => "")
245
+ assert_equivalent ["error", "question"], Issue.find(issues(:first_issue).id).tag_list
246
+ end
247
+
248
+ def test_tag_list_accessors_on_new_record
249
+ p = Issue.new(:description => 'Test')
250
+
251
+ assert p.tag_list.blank?
252
+ p.tag_list = "One, Two"
253
+ assert_equal "One, Two", p.tag_list.to_s
254
+ end
255
+
256
+ def test_clear_tag_list_with_nil
257
+ p = issues(:second_issue)
258
+
259
+ assert !p.tag_list.blank?
260
+ assert p.update_attributes(:tag_list => nil)
261
+ assert p.tag_list.blank?
262
+
263
+ assert p.reload.tag_list.blank?
264
+ end
265
+
266
+ def test_clear_tag_list_with_string
267
+ p = issues(:second_issue)
268
+
269
+ assert !p.tag_list.blank?
270
+ assert p.update_attributes(:tag_list => ' ')
271
+ assert p.tag_list.blank?
272
+
273
+ assert p.reload.tag_list.blank?
274
+ end
275
+
276
+ def test_tag_list_reset_on_reload
277
+ p = issues(:second_issue)
278
+ assert !p.tag_list.blank?
279
+ p.tag_list = nil
280
+ assert p.tag_list.blank?
281
+ assert !p.reload.tag_list.blank?
282
+ end
283
+
284
+ def test_instance_tag_counts
285
+ assert_tag_counts issues(:first_issue).tag_counts, :error => 3, :question => 3
286
+ end
287
+
288
+ def test_tag_list_populated_when_cache_nil
289
+ assert_nil issues(:first_issue).cached_tag_list
290
+ issues(:first_issue).save!
291
+ assert_equal issues(:first_issue).tag_list.to_s, issues(:first_issue).cached_tag_list
292
+ end
293
+
294
+ # def test_cached_tag_list_used
295
+ # issues(:first_issue).save!
296
+ # issues(:first_issue).reload
297
+
298
+ # assert_no_queries do
299
+ # assert_equivalent ["error", "question"], issues(:first_issue).tag_list
300
+ # end
301
+ # end
302
+
303
+ def test_cached_tag_list_not_used
304
+ # Load fixture and column information
305
+ issues(:first_issue).taggings(:reload)
306
+
307
+ # assert_queries 1 do
308
+ # # Tags association will be loaded
309
+ # issues(:first_issue).tag_list
310
+ # end
311
+ end
312
+
313
+ def test_cached_tag_list_updated
314
+ assert_nil issues(:first_issue).cached_tag_list
315
+ issues(:first_issue).save!
316
+ assert_equivalent ["question", "error"], RedmineCrm::TagList.from(issues(:first_issue).cached_tag_list)
317
+ issues(:first_issue).update_attributes!(:tag_list => "None")
318
+
319
+ assert_equal 'None', issues(:first_issue).cached_tag_list
320
+ assert_equal 'None', issues(:first_issue).reload.cached_tag_list
321
+ end
322
+
323
+ def test_clearing_cached_tag_list
324
+ # Generate the cached tag list
325
+ issues(:first_issue).save!
326
+
327
+ issues(:first_issue).update_attributes!(:tag_list => "")
328
+ assert_equal "", issues(:first_issue).cached_tag_list
329
+ end
330
+
331
+ def test_find_tagged_with_using_sti
332
+ special_Issue = SpecialIssue.create!(:description => "Test", :tag_list => "Random")
333
+
334
+ assert_equal [special_Issue], SpecialIssue.find_tagged_with("Random")
335
+ assert SpecialIssue.find_tagged_with("Random").include?(special_Issue)
336
+ end
337
+
338
+ # def test_tag_counts_using_sti
339
+ # SpecialIssue.create!(:description => "Test", :tag_list => "question")
340
+ # assert_tag_counts SpecialIssue.tag_counts, :question => 1
341
+ # end
342
+
343
+ def test_case_insensitivity
344
+ assert_difference "RedmineCrm::Tag.count", 1 do
345
+ Issue.create!(:description => "Test", :tag_list => "one")
346
+ Issue.create!(:description => "Test", :tag_list => "One")
347
+ end
348
+ assert_equal Issue.find_tagged_with("question"), Issue.find_tagged_with("question")
349
+ end
350
+
351
+ def test_tag_not_destroyed_when_unused
352
+ issues(:first_issue).tag_list.add("Random")
353
+ issues(:first_issue).save!
354
+
355
+ assert_no_difference 'RedmineCrm::Tag.count' do
356
+ issues(:first_issue).tag_list.remove("Random")
357
+ issues(:first_issue).save!
358
+ end
359
+ end
360
+
361
+ def test_tag_destroyed_when_unused
362
+ RedmineCrm::Tag.destroy_unused = true
363
+
364
+ issues(:first_issue).tag_list.add("Random")
365
+ issues(:first_issue).save!
366
+
367
+ assert_difference 'RedmineCrm::Tag.count', -1 do
368
+ issues(:first_issue).tag_list.remove("Random")
369
+ issues(:first_issue).save!
370
+ end
371
+ ensure
372
+ RedmineCrm::Tag.destroy_unused = false
373
+ end
374
+ end
375
+
376
+ # class ActsAsTaggableOnSteroidsFormTest < ActiveSupport::TestCase
377
+ # include ActionView::Helpers::FormHelper
378
+
379
+ # def test_tag_list_contents
380
+ # fields_for :Issue, issues(:first_issue) do |f|
381
+ # assert_match issues(:first_issue).tag_list.to_s, f.text_field(:tag_list)
382
+ # end
383
+ # end
384
+ # end