Revision 1298:4f746d8966dd

View differences:

.svn/pristine/00/0009a621965fc195e93ba67a7d3500cbcd38b084.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
class DocumentsController < ApplicationController
19
  default_search_scope :documents
20
  model_object Document
21
  before_filter :find_project_by_project_id, :only => [:index, :new, :create]
22
  before_filter :find_model_object, :except => [:index, :new, :create]
23
  before_filter :find_project_from_association, :except => [:index, :new, :create]
24
  before_filter :authorize
25

  
26
  helper :attachments
27

  
28
  def index
29
    @sort_by = %w(category date title author).include?(params[:sort_by]) ? params[:sort_by] : 'category'
30
    documents = @project.documents.includes(:attachments, :category).all
31
    case @sort_by
32
    when 'date'
33
      @grouped = documents.group_by {|d| d.updated_on.to_date }
34
    when 'title'
35
      @grouped = documents.group_by {|d| d.title.first.upcase}
36
    when 'author'
37
      @grouped = documents.select{|d| d.attachments.any?}.group_by {|d| d.attachments.last.author}
38
    else
39
      @grouped = documents.group_by(&:category)
40
    end
41
    @document = @project.documents.build
42
    render :layout => false if request.xhr?
43
  end
44

  
45
  def show
46
    @attachments = @document.attachments.all
47
  end
48

  
49
  def new
50
    @document = @project.documents.build
51
    @document.safe_attributes = params[:document]
52
  end
53

  
54
  def create
55
    @document = @project.documents.build
56
    @document.safe_attributes = params[:document]
57
    @document.save_attachments(params[:attachments])
58
    if @document.save
59
      render_attachment_warning_if_needed(@document)
60
      flash[:notice] = l(:notice_successful_create)
61
      redirect_to project_documents_path(@project)
62
    else
63
      render :action => 'new'
64
    end
65
  end
66

  
67
  def edit
68
  end
69

  
70
  def update
71
    @document.safe_attributes = params[:document]
72
    if request.put? and @document.save
73
      flash[:notice] = l(:notice_successful_update)
74
      redirect_to document_path(@document)
75
    else
76
      render :action => 'edit'
77
    end
78
  end
79

  
80
  def destroy
81
    @document.destroy if request.delete?
82
    redirect_to project_documents_path(@project)
83
  end
84

  
85
  def add_attachment
86
    attachments = Attachment.attach_files(@document, params[:attachments])
87
    render_attachment_warning_if_needed(@document)
88

  
89
    if attachments.present? && attachments[:files].present? && Setting.notified_events.include?('document_added')
90
      Mailer.attachments_added(attachments[:files]).deliver
91
    end
92
    redirect_to document_path(@document)
93
  end
94
end
.svn/pristine/00/002d478f30849d26745d0ec7b1c75e9c7796a254.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
require File.expand_path('../../test_helper', __FILE__)
19

  
20
class MailerTest < ActiveSupport::TestCase
21
  include Redmine::I18n
22
  include ActionDispatch::Assertions::SelectorAssertions
23
  fixtures :projects, :enabled_modules, :issues, :users, :members,
24
           :member_roles, :roles, :documents, :attachments, :news,
25
           :tokens, :journals, :journal_details, :changesets,
26
           :trackers, :projects_trackers,
27
           :issue_statuses, :enumerations, :messages, :boards, :repositories,
28
           :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions,
29
           :versions,
30
           :comments
31

  
32
  def setup
33
    ActionMailer::Base.deliveries.clear
34
    Setting.host_name = 'mydomain.foo'
35
    Setting.protocol = 'http'
36
    Setting.plain_text_mail = '0'
37
  end
38

  
39
  def test_generated_links_in_emails
40
    Setting.default_language = 'en'
41
    Setting.host_name = 'mydomain.foo'
42
    Setting.protocol = 'https'
43

  
44
    journal = Journal.find(3)
45
    assert Mailer.issue_edit(journal).deliver
46

  
47
    mail = last_email
48
    assert_not_nil mail
49

  
50
    assert_select_email do
51
      # link to the main ticket
52
      assert_select 'a[href=?]',
53
                    'https://mydomain.foo/issues/2#change-3',
54
                    :text => 'Feature request #2: Add ingredients categories'
55
      # link to a referenced ticket
56
      assert_select 'a[href=?][title=?]',
57
                    'https://mydomain.foo/issues/1',
58
                    'Can&#x27;t print recipes (New)',
59
                    :text => '#1'
60
      # link to a changeset
61
      assert_select 'a[href=?][title=?]',
62
                    'https://mydomain.foo/projects/ecookbook/repository/revisions/2',
63
                    'This commit fixes #1, #2 and references #1 &amp; #3',
64
                    :text => 'r2'
65
      # link to a description diff
66
      assert_select 'a[href=?][title=?]',
67
                    'https://mydomain.foo/journals/diff/3?detail_id=4',
68
                    'View differences',
69
                    :text => 'diff'
70
      # link to an attachment
71
      assert_select 'a[href=?]',
72
                    'https://mydomain.foo/attachments/download/4/source.rb',
73
                    :text => 'source.rb'
74
    end
75
  end
76

  
77
  def test_generated_links_with_prefix
78
    Setting.default_language = 'en'
79
    relative_url_root = Redmine::Utils.relative_url_root
80
    Setting.host_name = 'mydomain.foo/rdm'
81
    Setting.protocol = 'http'
82

  
83
    journal = Journal.find(3)
84
    assert Mailer.issue_edit(journal).deliver
85

  
86
    mail = last_email
87
    assert_not_nil mail
88

  
89
    assert_select_email do
90
      # link to the main ticket
91
      assert_select 'a[href=?]',
92
                    'http://mydomain.foo/rdm/issues/2#change-3',
93
                    :text => 'Feature request #2: Add ingredients categories'
94
      # link to a referenced ticket
95
      assert_select 'a[href=?][title=?]',
96
                    'http://mydomain.foo/rdm/issues/1',
97
                    'Can&#x27;t print recipes (New)',
98
                    :text => '#1'
99
      # link to a changeset
100
      assert_select 'a[href=?][title=?]',
101
                    'http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2',
102
                    'This commit fixes #1, #2 and references #1 &amp; #3',
103
                    :text => 'r2'
104
      # link to a description diff
105
      assert_select 'a[href=?][title=?]',
106
                    'http://mydomain.foo/rdm/journals/diff/3?detail_id=4',
107
                    'View differences',
108
                    :text => 'diff'
109
      # link to an attachment
110
      assert_select 'a[href=?]',
111
                    'http://mydomain.foo/rdm/attachments/download/4/source.rb',
112
                    :text => 'source.rb'
113
    end
114
  end
115

  
116
  def test_generated_links_with_prefix_and_no_relative_url_root
117
    Setting.default_language = 'en'
118
    relative_url_root = Redmine::Utils.relative_url_root
119
    Setting.host_name = 'mydomain.foo/rdm'
120
    Setting.protocol = 'http'
121
    Redmine::Utils.relative_url_root = nil
122

  
123
    journal = Journal.find(3)
124
    assert Mailer.issue_edit(journal).deliver
125

  
126
    mail = last_email
127
    assert_not_nil mail
128

  
129
    assert_select_email do
130
      # link to the main ticket
131
      assert_select 'a[href=?]',
132
                    'http://mydomain.foo/rdm/issues/2#change-3',
133
                    :text => 'Feature request #2: Add ingredients categories'
134
      # link to a referenced ticket
135
      assert_select 'a[href=?][title=?]',
136
                    'http://mydomain.foo/rdm/issues/1',
137
                    'Can&#x27;t print recipes (New)',
138
                    :text => '#1'
139
      # link to a changeset
140
      assert_select 'a[href=?][title=?]',
141
                    'http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2',
142
                    'This commit fixes #1, #2 and references #1 &amp; #3',
143
                    :text => 'r2'
144
      # link to a description diff
145
      assert_select 'a[href=?][title=?]',
146
                    'http://mydomain.foo/rdm/journals/diff/3?detail_id=4',
147
                    'View differences',
148
                    :text => 'diff'
149
      # link to an attachment
150
      assert_select 'a[href=?]',
151
                    'http://mydomain.foo/rdm/attachments/download/4/source.rb',
152
                    :text => 'source.rb'
153
    end
154
  ensure
155
    # restore it
156
    Redmine::Utils.relative_url_root = relative_url_root
157
  end
158

  
159
  def test_email_headers
160
    issue = Issue.find(1)
161
    Mailer.issue_add(issue).deliver
162
    mail = last_email
163
    assert_not_nil mail
164
    assert_equal 'OOF', mail.header['X-Auto-Response-Suppress'].to_s
165
    assert_equal 'auto-generated', mail.header['Auto-Submitted'].to_s
166
    assert_equal '<redmine.example.net>', mail.header['List-Id'].to_s
167
  end
168

  
169
  def test_email_headers_should_include_sender
170
    issue = Issue.find(1)
171
    Mailer.issue_add(issue).deliver
172
    mail = last_email
173
    assert_equal issue.author.login, mail.header['X-Redmine-Sender'].to_s
174
  end
175

  
176
  def test_plain_text_mail
177
    Setting.plain_text_mail = 1
178
    journal = Journal.find(2)
179
    Mailer.issue_edit(journal).deliver
180
    mail = last_email
181
    assert_equal "text/plain; charset=UTF-8", mail.content_type
182
    assert_equal 0, mail.parts.size
183
    assert !mail.encoded.include?('href')
184
  end
185

  
186
  def test_html_mail
187
    Setting.plain_text_mail = 0
188
    journal = Journal.find(2)
189
    Mailer.issue_edit(journal).deliver
190
    mail = last_email
191
    assert_equal 2, mail.parts.size
192
    assert mail.encoded.include?('href')
193
  end
194

  
195
  def test_from_header
196
    with_settings :mail_from => 'redmine@example.net' do
197
      Mailer.test_email(User.find(1)).deliver
198
    end
199
    mail = last_email
200
    assert_equal 'redmine@example.net', mail.from_addrs.first
201
  end
202

  
203
  def test_from_header_with_phrase
204
    with_settings :mail_from => 'Redmine app <redmine@example.net>' do
205
      Mailer.test_email(User.find(1)).deliver
206
    end
207
    mail = last_email
208
    assert_equal 'redmine@example.net', mail.from_addrs.first
209
    assert_equal 'Redmine app <redmine@example.net>', mail.header['From'].to_s
210
  end
211

  
212
  def test_should_not_send_email_without_recipient
213
    news = News.first
214
    user = news.author
215
    # Remove members except news author
216
    news.project.memberships.each {|m| m.destroy unless m.user == user}
217

  
218
    user.pref[:no_self_notified] = false
219
    user.pref.save
220
    User.current = user
221
    Mailer.news_added(news.reload).deliver
222
    assert_equal 1, last_email.bcc.size
223

  
224
    # nobody to notify
225
    user.pref[:no_self_notified] = true
226
    user.pref.save
227
    User.current = user
228
    ActionMailer::Base.deliveries.clear
229
    Mailer.news_added(news.reload).deliver
230
    assert ActionMailer::Base.deliveries.empty?
231
  end
232

  
233
  def test_issue_add_message_id
234
    issue = Issue.find(1)
235
    Mailer.issue_add(issue).deliver
236
    mail = last_email
237
    assert_equal Mailer.message_id_for(issue), mail.message_id
238
    assert_nil mail.references
239
  end
240

  
241
  def test_issue_edit_message_id
242
    journal = Journal.find(1)
243
    Mailer.issue_edit(journal).deliver
244
    mail = last_email
245
    assert_equal Mailer.message_id_for(journal), mail.message_id
246
    assert_include Mailer.message_id_for(journal.issue), mail.references
247
    assert_select_email do
248
      # link to the update
249
      assert_select "a[href=?]",
250
                    "http://mydomain.foo/issues/#{journal.journalized_id}#change-#{journal.id}"
251
    end
252
  end
253

  
254
  def test_message_posted_message_id
255
    message = Message.find(1)
256
    Mailer.message_posted(message).deliver
257
    mail = last_email
258
    assert_equal Mailer.message_id_for(message), mail.message_id
259
    assert_nil mail.references
260
    assert_select_email do
261
      # link to the message
262
      assert_select "a[href=?]",
263
                    "http://mydomain.foo/boards/#{message.board.id}/topics/#{message.id}",
264
                    :text => message.subject
265
    end
266
  end
267

  
268
  def test_reply_posted_message_id
269
    message = Message.find(3)
270
    Mailer.message_posted(message).deliver
271
    mail = last_email
272
    assert_equal Mailer.message_id_for(message), mail.message_id
273
    assert_include Mailer.message_id_for(message.parent), mail.references
274
    assert_select_email do
275
      # link to the reply
276
      assert_select "a[href=?]",
277
                    "http://mydomain.foo/boards/#{message.board.id}/topics/#{message.root.id}?r=#{message.id}#message-#{message.id}",
278
                    :text => message.subject
279
    end
280
  end
281

  
282
  test "#issue_add should notify project members" do
283
    issue = Issue.find(1)
284
    assert Mailer.issue_add(issue).deliver
285
    assert last_email.bcc.include?('dlopper@somenet.foo')
286
  end
287

  
288
  test "#issue_add should not notify project members that are not allow to view the issue" do
289
    issue = Issue.find(1)
290
    Role.find(2).remove_permission!(:view_issues)
291
    assert Mailer.issue_add(issue).deliver
292
    assert !last_email.bcc.include?('dlopper@somenet.foo')
293
  end
294

  
295
  test "#issue_add should notify issue watchers" do
296
    issue = Issue.find(1)
297
    user = User.find(9)
298
    # minimal email notification options
299
    user.pref[:no_self_notified] = '1'
300
    user.pref.save
301
    user.mail_notification = false
302
    user.save
303

  
304
    Watcher.create!(:watchable => issue, :user => user)
305
    assert Mailer.issue_add(issue).deliver
306
    assert last_email.bcc.include?(user.mail)
307
  end
308

  
309
  test "#issue_add should not notify watchers not allowed to view the issue" do
310
    issue = Issue.find(1)
311
    user = User.find(9)
312
    Watcher.create!(:watchable => issue, :user => user)
313
    Role.non_member.remove_permission!(:view_issues)
314
    assert Mailer.issue_add(issue).deliver
315
    assert !last_email.bcc.include?(user.mail)
316
  end
317

  
318
  # test mailer methods for each language
319
  def test_issue_add
320
    issue = Issue.find(1)
321
    valid_languages.each do |lang|
322
      Setting.default_language = lang.to_s
323
      assert Mailer.issue_add(issue).deliver
324
    end
325
  end
326

  
327
  def test_issue_edit
328
    journal = Journal.find(1)
329
    valid_languages.each do |lang|
330
      Setting.default_language = lang.to_s
331
      assert Mailer.issue_edit(journal).deliver
332
    end
333
  end
334

  
335
  def test_issue_edit_should_send_private_notes_to_users_with_permission_only
336
    journal = Journal.find(1)
337
    journal.private_notes = true
338
    journal.save!
339

  
340
    Role.find(2).add_permission! :view_private_notes
341
    Mailer.issue_edit(journal).deliver
342
    assert_equal %w(dlopper@somenet.foo jsmith@somenet.foo), ActionMailer::Base.deliveries.last.bcc.sort
343

  
344
    Role.find(2).remove_permission! :view_private_notes
345
    Mailer.issue_edit(journal).deliver
346
    assert_equal %w(jsmith@somenet.foo), ActionMailer::Base.deliveries.last.bcc.sort
347
  end
348

  
349
  def test_issue_edit_should_send_private_notes_to_watchers_with_permission_only
350
    Issue.find(1).set_watcher(User.find_by_login('someone'))
351
    journal = Journal.find(1)
352
    journal.private_notes = true
353
    journal.save!
354

  
355
    Role.non_member.add_permission! :view_private_notes
356
    Mailer.issue_edit(journal).deliver
357
    assert_include 'someone@foo.bar', ActionMailer::Base.deliveries.last.bcc.sort
358

  
359
    Role.non_member.remove_permission! :view_private_notes
360
    Mailer.issue_edit(journal).deliver
361
    assert_not_include 'someone@foo.bar', ActionMailer::Base.deliveries.last.bcc.sort
362
  end
363

  
364
  def test_document_added
365
    document = Document.find(1)
366
    valid_languages.each do |lang|
367
      Setting.default_language = lang.to_s
368
      assert Mailer.document_added(document).deliver
369
    end
370
  end
371

  
372
  def test_attachments_added
373
    attachements = [ Attachment.find_by_container_type('Document') ]
374
    valid_languages.each do |lang|
375
      Setting.default_language = lang.to_s
376
      assert Mailer.attachments_added(attachements).deliver
377
    end
378
  end
379

  
380
  def test_version_file_added
381
    attachements = [ Attachment.find_by_container_type('Version') ]
382
    assert Mailer.attachments_added(attachements).deliver
383
    assert_not_nil last_email.bcc
384
    assert last_email.bcc.any?
385
    assert_select_email do
386
      assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
387
    end
388
  end
389

  
390
  def test_project_file_added
391
    attachements = [ Attachment.find_by_container_type('Project') ]
392
    assert Mailer.attachments_added(attachements).deliver
393
    assert_not_nil last_email.bcc
394
    assert last_email.bcc.any?
395
    assert_select_email do
396
      assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
397
    end
398
  end
399

  
400
  def test_news_added
401
    news = News.first
402
    valid_languages.each do |lang|
403
      Setting.default_language = lang.to_s
404
      assert Mailer.news_added(news).deliver
405
    end
406
  end
407

  
408
  def test_news_comment_added
409
    comment = Comment.find(2)
410
    valid_languages.each do |lang|
411
      Setting.default_language = lang.to_s
412
      assert Mailer.news_comment_added(comment).deliver
413
    end
414
  end
415

  
416
  def test_message_posted
417
    message = Message.first
418
    recipients = ([message.root] + message.root.children).collect {|m| m.author.mail if m.author}
419
    recipients = recipients.compact.uniq
420
    valid_languages.each do |lang|
421
      Setting.default_language = lang.to_s
422
      assert Mailer.message_posted(message).deliver
423
    end
424
  end
425

  
426
  def test_wiki_content_added
427
    content = WikiContent.find(1)
428
    valid_languages.each do |lang|
429
      Setting.default_language = lang.to_s
430
      assert_difference 'ActionMailer::Base.deliveries.size' do
431
        assert Mailer.wiki_content_added(content).deliver
432
        assert_select_email do
433
          assert_select 'a[href=?]',
434
            'http://mydomain.foo/projects/ecookbook/wiki/CookBook_documentation',
435
            :text => 'CookBook documentation'
436
        end
437
      end
438
    end
439
  end
440

  
441
  def test_wiki_content_updated
442
    content = WikiContent.find(1)
443
    valid_languages.each do |lang|
444
      Setting.default_language = lang.to_s
445
      assert_difference 'ActionMailer::Base.deliveries.size' do
446
        assert Mailer.wiki_content_updated(content).deliver
447
        assert_select_email do
448
          assert_select 'a[href=?]',
449
            'http://mydomain.foo/projects/ecookbook/wiki/CookBook_documentation',
450
            :text => 'CookBook documentation'
451
        end
452
      end
453
    end
454
  end
455

  
456
  def test_account_information
457
    user = User.find(2)
458
    valid_languages.each do |lang|
459
      user.update_attribute :language, lang.to_s
460
      user.reload
461
      assert Mailer.account_information(user, 'pAsswORd').deliver
462
    end
463
  end
464

  
465
  def test_lost_password
466
    token = Token.find(2)
467
    valid_languages.each do |lang|
468
      token.user.update_attribute :language, lang.to_s
469
      token.reload
470
      assert Mailer.lost_password(token).deliver
471
    end
472
  end
473

  
474
  def test_register
475
    token = Token.find(1)
476
    Setting.host_name = 'redmine.foo'
477
    Setting.protocol = 'https'
478

  
479
    valid_languages.each do |lang|
480
      token.user.update_attribute :language, lang.to_s
481
      token.reload
482
      ActionMailer::Base.deliveries.clear
483
      assert Mailer.register(token).deliver
484
      mail = last_email
485
      assert_select_email do
486
        assert_select "a[href=?]",
487
                      "https://redmine.foo/account/activate?token=#{token.value}",
488
                      :text => "https://redmine.foo/account/activate?token=#{token.value}"
489
      end
490
    end
491
  end
492

  
493
  def test_test
494
    user = User.find(1)
495
    valid_languages.each do |lang|
496
      user.update_attribute :language, lang.to_s
497
      assert Mailer.test_email(user).deliver
498
    end
499
  end
500

  
501
  def test_reminders
502
    Mailer.reminders(:days => 42)
503
    assert_equal 1, ActionMailer::Base.deliveries.size
504
    mail = last_email
505
    assert mail.bcc.include?('dlopper@somenet.foo')
506
    assert_mail_body_match 'Bug #3: Error 281 when updating a recipe', mail
507
    assert_equal '1 issue(s) due in the next 42 days', mail.subject
508
  end
509

  
510
  def test_reminders_should_not_include_closed_issues
511
    with_settings :default_language => 'en' do
512
      Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 5,
513
                      :subject => 'Closed issue', :assigned_to_id => 3,
514
                      :due_date => 5.days.from_now,
515
                      :author_id => 2)
516
      ActionMailer::Base.deliveries.clear
517

  
518
      Mailer.reminders(:days => 42)
519
      assert_equal 1, ActionMailer::Base.deliveries.size
520
      mail = last_email
521
      assert mail.bcc.include?('dlopper@somenet.foo')
522
      assert_mail_body_no_match 'Closed issue', mail
523
    end
524
  end
525

  
526
  def test_reminders_for_users
527
    Mailer.reminders(:days => 42, :users => ['5'])
528
    assert_equal 0, ActionMailer::Base.deliveries.size # No mail for dlopper
529
    Mailer.reminders(:days => 42, :users => ['3'])
530
    assert_equal 1, ActionMailer::Base.deliveries.size # No mail for dlopper
531
    mail = last_email
532
    assert mail.bcc.include?('dlopper@somenet.foo')
533
    assert_mail_body_match 'Bug #3: Error 281 when updating a recipe', mail
534
  end
535

  
536
  def test_reminder_should_include_issues_assigned_to_groups
537
    with_settings :default_language => 'en' do
538
      group = Group.generate!
539
      group.users << User.find(2)
540
      group.users << User.find(3)
541

  
542
      Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 1,
543
                      :subject => 'Assigned to group', :assigned_to => group,
544
                      :due_date => 5.days.from_now,
545
                      :author_id => 2)
546
      ActionMailer::Base.deliveries.clear
547

  
548
      Mailer.reminders(:days => 7)
549
      assert_equal 2, ActionMailer::Base.deliveries.size
550
      assert_equal %w(dlopper@somenet.foo jsmith@somenet.foo), ActionMailer::Base.deliveries.map(&:bcc).flatten.sort
551
      ActionMailer::Base.deliveries.each do |mail|
552
        assert_mail_body_match 'Assigned to group', mail
553
      end
554
    end
555
  end
556

  
557
  def test_mailer_should_not_change_locale
558
    Setting.default_language = 'en'
559
    # Set current language to italian
560
    set_language_if_valid 'it'
561
    # Send an email to a french user
562
    user = User.find(1)
563
    user.language = 'fr'
564
    Mailer.account_activated(user).deliver
565
    mail = last_email
566
    assert_mail_body_match 'Votre compte', mail
567

  
568
    assert_equal :it, current_language
569
  end
570

  
571
  def test_with_deliveries_off
572
    Mailer.with_deliveries false do
573
      Mailer.test_email(User.find(1)).deliver
574
    end
575
    assert ActionMailer::Base.deliveries.empty?
576
    # should restore perform_deliveries
577
    assert ActionMailer::Base.perform_deliveries
578
  end
579

  
580
  def test_layout_should_include_the_emails_header
581
    with_settings :emails_header => "*Header content*" do
582
      assert Mailer.test_email(User.find(1)).deliver
583
      assert_select_email do
584
        assert_select ".header" do
585
          assert_select "strong", :text => "Header content"
586
        end
587
      end
588
    end
589
  end
590

  
591
  def test_should_escape_html_templates_only
592
    Issue.generate!(:project_id => 1, :tracker_id => 1, :subject => 'Subject with a <tag>')
593
    mail = last_email
594
    assert_equal 2, mail.parts.size
595
    assert_include '<tag>', text_part.body.encoded
596
    assert_include '&lt;tag&gt;', html_part.body.encoded
597
  end
598

  
599
  private
600

  
601
  def last_email
602
    mail = ActionMailer::Base.deliveries.last
603
    assert_not_nil mail
604
    mail
605
  end
606

  
607
  def text_part
608
    last_email.parts.detect {|part| part.content_type.include?('text/plain')}
609
  end
610

  
611
  def html_part
612
    last_email.parts.detect {|part| part.content_type.include?('text/html')}
613
  end
614
end
.svn/pristine/00/007e22f777adc578342260747f72f3fcfceb129d.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
class ProjectCustomField < CustomField
19
  def type_name
20
    :label_project_plural
21
  end
22
end
.svn/pristine/00/0081b5051789911922bdd0b18a28f0ad87c64e8d.svn-base
1
<div class="contextual">
2
<%= link_to l(:label_tracker_new), new_tracker_path, :class => 'icon icon-add' %>
3
<%= link_to l(:field_summary), fields_trackers_path, :class => 'icon icon-summary' %>
4
</div>
5

  
6
<h2><%=l(:label_tracker_plural)%></h2>
7

  
8
<table class="list">
9
  <thead><tr>
10
  <th><%=l(:label_tracker)%></th>
11
  <th></th>
12
  <th><%=l(:button_sort)%></th>
13
  <th></th>
14
  </tr></thead>
15
  <tbody>
16
<% for tracker in @trackers %>
17
  <tr class="<%= cycle("odd", "even") %>">
18
  <td><%= link_to h(tracker.name), edit_tracker_path(tracker) %></td>
19
  <td align="center">
20
    <% unless tracker.workflow_rules.count > 0 %>
21
      <span class="icon icon-warning">
22
        <%= l(:text_tracker_no_workflow) %> (<%= link_to l(:button_edit), workflows_edit_path(:tracker_id => tracker) %>)
23
      </span>
24
    <% end %>
25
  </td>
26
  <td align="center" style="width:15%;">
27
    <%= reorder_links('tracker', {:action => 'update', :id => tracker}, :put) %>
28
  </td>
29
  <td class="buttons">
30
    <%= delete_link tracker_path(tracker) %>
31
  </td>
32
  </tr>
33
<% end %>
34
  </tbody>
35
</table>
36

  
37
<p class="pagination"><%= pagination_links_full @tracker_pages %></p>
38

  
39
<% html_title(l(:label_tracker_plural)) -%>
.svn/pristine/00/00bd76ee7194e922fe9340f2d39d910c9f79b20e.svn-base
1
module ObjectHelpers
2
  def User.generate!(attributes={})
3
    @generated_user_login ||= 'user0'
4
    @generated_user_login.succ!
5
    user = User.new(attributes)
6
    user.login = @generated_user_login.dup if user.login.blank?
7
    user.mail = "#{@generated_user_login}@example.com" if user.mail.blank?
8
    user.firstname = "Bob" if user.firstname.blank?
9
    user.lastname = "Doe" if user.lastname.blank?
10
    yield user if block_given?
11
    user.save!
12
    user
13
  end
14

  
15
  def User.add_to_project(user, project, roles=nil)
16
    roles = Role.find(1) if roles.nil?
17
    roles = [roles] unless roles.is_a?(Array)
18
    Member.create!(:principal => user, :project => project, :roles => roles)
19
  end
20

  
21
  def Group.generate!(attributes={})
22
    @generated_group_name ||= 'Group 0'
23
    @generated_group_name.succ!
24
    group = Group.new(attributes)
25
    group.name = @generated_group_name.dup if group.name.blank?
26
    yield group if block_given?
27
    group.save!
28
    group
29
  end
30

  
31
  def Project.generate!(attributes={})
32
    @generated_project_identifier ||= 'project-0000'
33
    @generated_project_identifier.succ!
34
    project = Project.new(attributes)
35
    project.name = @generated_project_identifier.dup if project.name.blank?
36
    project.identifier = @generated_project_identifier.dup if project.identifier.blank?
37
    yield project if block_given?
38
    project.save!
39
    project
40
  end
41

  
42
  def Project.generate_with_parent!(parent, attributes={})
43
    project = Project.generate!(attributes)
44
    project.set_parent!(parent)
45
    project
46
  end
47

  
48
  def Tracker.generate!(attributes={})
49
    @generated_tracker_name ||= 'Tracker 0'
50
    @generated_tracker_name.succ!
51
    tracker = Tracker.new(attributes)
52
    tracker.name = @generated_tracker_name.dup if tracker.name.blank?
53
    yield tracker if block_given?
54
    tracker.save!
55
    tracker
56
  end
57

  
58
  def Role.generate!(attributes={})
59
    @generated_role_name ||= 'Role 0'
60
    @generated_role_name.succ!
61
    role = Role.new(attributes)
62
    role.name = @generated_role_name.dup if role.name.blank?
63
    yield role if block_given?
64
    role.save!
65
    role
66
  end
67

  
68
  def Issue.generate!(attributes={})
69
    issue = Issue.new(attributes)
70
    issue.project ||= Project.find(1)
71
    issue.tracker ||= issue.project.trackers.first
72
    issue.subject = 'Generated' if issue.subject.blank?
73
    issue.author ||= User.find(2)
74
    yield issue if block_given?
75
    issue.save!
76
    issue
77
  end
78

  
79
  # Generates an issue with 2 children and a grandchild
80
  def Issue.generate_with_descendants!(attributes={})
81
    issue = Issue.generate!(attributes)
82
    child = Issue.generate!(:project => issue.project, :subject => 'Child1', :parent_issue_id => issue.id)
83
    Issue.generate!(:project => issue.project, :subject => 'Child2', :parent_issue_id => issue.id)
84
    Issue.generate!(:project => issue.project, :subject => 'Child11', :parent_issue_id => child.id)
85
    issue.reload
86
  end
87

  
88
  def Journal.generate!(attributes={})
89
    journal = Journal.new(attributes)
90
    journal.user ||= User.first
91
    journal.journalized ||= Issue.first
92
    yield journal if block_given?
93
    journal.save!
94
    journal
95
  end
96

  
97
  def Version.generate!(attributes={})
98
    @generated_version_name ||= 'Version 0'
99
    @generated_version_name.succ!
100
    version = Version.new(attributes)
101
    version.name = @generated_version_name.dup if version.name.blank?
102
    yield version if block_given?
103
    version.save!
104
    version
105
  end
106

  
107
  def TimeEntry.generate!(attributes={})
108
    entry = TimeEntry.new(attributes)
109
    entry.user ||= User.find(2)
110
    entry.issue ||= Issue.find(1) unless entry.project
111
    entry.project ||= entry.issue.project
112
    entry.activity ||= TimeEntryActivity.first
113
    entry.spent_on ||= Date.today
114
    entry.hours ||= 1.0
115
    entry.save!
116
    entry
117
  end
118

  
119
  def AuthSource.generate!(attributes={})
120
    @generated_auth_source_name ||= 'Auth 0'
121
    @generated_auth_source_name.succ!
122
    source = AuthSource.new(attributes)
123
    source.name = @generated_auth_source_name.dup if source.name.blank?
124
    yield source if block_given?
125
    source.save!
126
    source
127
  end
128

  
129
  def Board.generate!(attributes={})
130
    @generated_board_name ||= 'Forum 0'
131
    @generated_board_name.succ!
132
    board = Board.new(attributes)
133
    board.name = @generated_board_name.dup if board.name.blank?
134
    board.description = @generated_board_name.dup if board.description.blank?
135
    yield board if block_given?
136
    board.save!
137
    board
138
  end
139

  
140
  def Attachment.generate!(attributes={})
141
    @generated_filename ||= 'testfile0'
142
    @generated_filename.succ!
143
    attributes = attributes.dup
144
    attachment = Attachment.new(attributes)
145
    attachment.container ||= Issue.find(1)
146
    attachment.author ||= User.find(2)
147
    attachment.filename = @generated_filename.dup if attachment.filename.blank?
148
    attachment.save!
149
    attachment
150
  end
151

  
152
  def CustomField.generate!(attributes={})
153
    @generated_custom_field_name ||= 'Custom field 0'
154
    @generated_custom_field_name.succ!
155
    field = new(attributes)
156
    field.name = @generated_custom_field_name.dup if field.name.blank?
157
    field.field_format = 'string' if field.field_format.blank?
158
    yield field if block_given?
159
    field.save!
160
    field
161
  end
162
end
.svn/pristine/00/00c1a9b51dc321ecb980f25b62c13dfa7fd628ff.svn-base
1
<%= error_messages_for 'auth_source' %>
2

  
3
<div class="box tabular">
4
  <p><%= f.text_field :name, :required => true %></p>
5
  <p><%= f.text_field :host, :required => true %></p>
6
  <p><%= f.text_field :port, :required => true, :size => 6 %> <%= f.check_box :tls, :no_label => true %> LDAPS</p>
7
  <p><%= f.text_field :account %></p>
8
  <p><%= f.password_field :account_password, :label => :field_password,
9
           :name => 'dummy_password',
10
           :value => ((@auth_source.new_record? || @auth_source.account_password.blank?) ? '' : ('x'*15)),
11
           :onfocus => "this.value=''; this.name='auth_source[account_password]';",
12
           :onchange => "this.name='auth_source[account_password]';" %></p>
13
  <p><%= f.text_field :base_dn, :required => true, :size => 60 %></p>
14
  <p><%= f.text_field :filter, :size => 60, :label => :field_auth_source_ldap_filter %></p>
15
  <p><%= f.text_field :timeout, :size => 4 %></p>
16
  <p><%= f.check_box :onthefly_register, :label => :field_onthefly %></p>
17
</div>
18

  
19
<fieldset class="box tabular"><legend><%=l(:label_attribute_plural)%></legend>
20
  <p><%= f.text_field :attr_login, :required => true, :size => 20 %></p>
21
  <p><%= f.text_field :attr_firstname, :size => 20 %></p>
22
  <p><%= f.text_field :attr_lastname, :size => 20 %></p>
23
  <p><%= f.text_field :attr_mail, :size => 20 %></p>
24
</fieldset>
.svn/pristine/00/00c4bd6691f32db8720a826db98aecc930f926d9.svn-base
1
# $Id: entry.rb 123 2006-05-18 03:52:38Z blackhedd $
2
#
3
# LDAP Entry (search-result) support classes
4
#
5
#
6
#----------------------------------------------------------------------------
7
#
8
# Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
9
#
10
# Gmail: garbagecat10
11
#
12
# This program is free software; you can redistribute it and/or modify
13
# it under the terms of the GNU General Public License as published by
14
# the Free Software Foundation; either version 2 of the License, or
15
# (at your option) any later version.
16
#
17
# This program is distributed in the hope that it will be useful,
18
# but WITHOUT ANY WARRANTY; without even the implied warranty of
19
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
# GNU General Public License for more details.
21
#
22
# You should have received a copy of the GNU General Public License
23
# along with this program; if not, write to the Free Software
24
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
25
#
26
#---------------------------------------------------------------------------
27
#
28

  
29

  
30

  
31

  
32
module Net
33
class LDAP
34

  
35

  
36
  # Objects of this class represent individual entries in an LDAP
37
  # directory. User code generally does not instantiate this class.
38
  # Net::LDAP#search provides objects of this class to user code,
39
  # either as block parameters or as return values.
40
  #
41
  # In LDAP-land, an "entry" is a collection of attributes that are
42
  # uniquely and globally identified by a DN ("Distinguished Name").
43
  # Attributes are identified by short, descriptive words or phrases.
44
  # Although a directory is
45
  # free to implement any attribute name, most of them follow rigorous
46
  # standards so that the range of commonly-encountered attribute
47
  # names is not large.
48
  #
49
  # An attribute name is case-insensitive. Most directories also
50
  # restrict the range of characters allowed in attribute names.
51
  # To simplify handling attribute names, Net::LDAP::Entry
52
  # internally converts them to a standard format. Therefore, the
53
  # methods which take attribute names can take Strings or Symbols,
54
  # and work correctly regardless of case or capitalization.
55
  #
56
  # An attribute consists of zero or more data items called
57
  # <i>values.</i> An entry is the combination of a unique DN, a set of attribute
58
  # names, and a (possibly-empty) array of values for each attribute.
59
  #
60
  # Class Net::LDAP::Entry provides convenience methods for dealing
61
  # with LDAP entries.
62
  # In addition to the methods documented below, you may access individual
63
  # attributes of an entry simply by giving the attribute name as
64
  # the name of a method call. For example:
65
  #  ldap.search( ... ) do |entry|
66
  #    puts "Common name: #{entry.cn}"
67
  #    puts "Email addresses:"
68
  #      entry.mail.each {|ma| puts ma}
69
  #  end
70
  # If you use this technique to access an attribute that is not present
71
  # in a particular Entry object, a NoMethodError exception will be raised.
72
  #
73
  #--
74
  # Ugly problem to fix someday: We key off the internal hash with
75
  # a canonical form of the attribute name: convert to a string,
76
  # downcase, then take the symbol. Unfortunately we do this in
77
  # at least three places. Should do it in ONE place.
78
  class Entry
79

  
80
    # This constructor is not generally called by user code.
81
    def initialize dn = nil # :nodoc:
82
      @myhash = Hash.new {|k,v| k[v] = [] }
83
      @myhash[:dn] = [dn]
84
    end
85

  
86

  
87
    def []= name, value # :nodoc:
88
      sym = name.to_s.downcase.intern
89
      @myhash[sym] = value
90
    end
91

  
92

  
93
    #--
94
    # We have to deal with this one as we do with []=
95
    # because this one and not the other one gets called
96
    # in formulations like entry["CN"] << cn.
97
    #
98
    def [] name # :nodoc:
99
      name = name.to_s.downcase.intern unless name.is_a?(Symbol)
100
      @myhash[name]
101
    end
102

  
103
    # Returns the dn of the Entry as a String.
104
    def dn
105
      self[:dn][0]
106
    end
107

  
108
    # Returns an array of the attribute names present in the Entry.
109
    def attribute_names
110
      @myhash.keys
111
    end
112

  
113
    # Accesses each of the attributes present in the Entry.
114
    # Calls a user-supplied block with each attribute in turn,
115
    # passing two arguments to the block: a Symbol giving
116
    # the name of the attribute, and a (possibly empty)
117
    # Array of data values.
118
    #
119
    def each
120
      if block_given?
121
        attribute_names.each {|a|
122
          attr_name,values = a,self[a]
123
          yield attr_name, values
124
        }
125
      end
126
    end
127

  
128
    alias_method :each_attribute, :each
129

  
130

  
131
    #--
132
    # Convenience method to convert unknown method names
133
    # to attribute references. Of course the method name
134
    # comes to us as a symbol, so let's save a little time
135
    # and not bother with the to_s.downcase two-step.
136
    # Of course that means that a method name like mAIL
137
    # won't work, but we shouldn't be encouraging that
138
    # kind of bad behavior in the first place.
139
    # Maybe we should thow something if the caller sends
140
    # arguments or a block...
141
    #
142
    def method_missing *args, &block # :nodoc:
143
      s = args[0].to_s.downcase.intern
144
      if attribute_names.include?(s)
145
        self[s]
146
      elsif s.to_s[-1] == 61 and s.to_s.length > 1
147
        value = args[1] or raise RuntimeError.new( "unable to set value" )
148
        value = [value] unless value.is_a?(Array)
149
        name = s.to_s[0..-2].intern
150
        self[name] = value
151
      else
152
        raise NoMethodError.new( "undefined method '#{s}'" )
153
      end
154
    end
155

  
156
    def write
157
    end
158

  
159
  end # class Entry
160

  
161

  
162
end # class LDAP
163
end # module Net
164

  
165

  
.svn/pristine/01/011d952bc7773843d5a8219df22dce0959479d6d.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
require File.expand_path('../../test_helper', __FILE__)
19

  
20
class DocumentCategoryTest < ActiveSupport::TestCase
21
  fixtures :enumerations, :documents, :issues
22

  
23
  def test_should_be_an_enumeration
24
    assert DocumentCategory.ancestors.include?(Enumeration)
25
  end
26

  
27
  def test_objects_count
28
    assert_equal 2, DocumentCategory.find_by_name("Uncategorized").objects_count
29
    assert_equal 0, DocumentCategory.find_by_name("User documentation").objects_count
30
  end
31

  
32
  def test_option_name
33
    assert_equal :enumeration_doc_categories, DocumentCategory.new.option_name
34
  end
35
end
.svn/pristine/01/01272907f6842a5e924d61c923ee0994110ab686.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
require File.expand_path('../../../../../test_helper', __FILE__)
19

  
20
class Redmine::MenuManager::MenuHelperTest < HelperTestCase
21
  include Redmine::MenuManager::MenuHelper
22
  include ActionController::Assertions::SelectorAssertions
23
  fixtures :users, :members, :projects, :enabled_modules
24

  
25
  # Used by assert_select
26
  def html_document
27
    HTML::Document.new(@response.body)
28
  end
29

  
30
  def setup
31
    super
32
    @response = ActionController::TestResponse.new
33
    # Stub the current menu item in the controller
34
    def current_menu_item
35
      :index
36
    end
37
  end
38

  
39

  
40
  context "MenuManager#current_menu_item" do
41
    should "be tested"
42
  end
43

  
44
  context "MenuManager#render_main_menu" do
45
    should "be tested"
46
  end
47

  
48
  context "MenuManager#render_menu" do
49
    should "be tested"
50
  end
51

  
52
  context "MenuManager#menu_item_and_children" do
53
    should "be tested"
54
  end
55

  
56
  context "MenuManager#extract_node_details" do
57
    should "be tested"
58
  end
59

  
60
  def test_render_single_menu_node
61
    node = Redmine::MenuManager::MenuItem.new(:testing, '/test', { })
62
    @response.body = render_single_menu_node(node, 'This is a test', node.url, false)
63

  
64
    assert_select("a.testing", "This is a test")
65
  end
66

  
67
  def test_render_menu_node
68
    single_node = Redmine::MenuManager::MenuItem.new(:single_node, '/test', { })
69
    @response.body = render_menu_node(single_node, nil)
70

  
71
    assert_select("li") do
72
      assert_select("a.single-node", "Single node")
73
    end
74
  end
75

  
76
  def test_render_menu_node_with_nested_items
77
    parent_node = Redmine::MenuManager::MenuItem.new(:parent_node, '/test', { })
78
    parent_node << Redmine::MenuManager::MenuItem.new(:child_one_node, '/test', { })
79
    parent_node << Redmine::MenuManager::MenuItem.new(:child_two_node, '/test', { })
80
    parent_node <<
81
      Redmine::MenuManager::MenuItem.new(:child_three_node, '/test', { }) <<
82
      Redmine::MenuManager::MenuItem.new(:child_three_inner_node, '/test', { })
83

  
84
    @response.body = render_menu_node(parent_node, nil)
85

  
86
    assert_select("li") do
87
      assert_select("a.parent-node", "Parent node")
88
      assert_select("ul") do
89
        assert_select("li a.child-one-node", "Child one node")
90
        assert_select("li a.child-two-node", "Child two node")
91
        assert_select("li") do
92
          assert_select("a.child-three-node", "Child three node")
93
          assert_select("ul") do
94
            assert_select("li a.child-three-inner-node", "Child three inner node")
95
          end
96
        end
97
      end
98
    end
99

  
100
  end
101

  
102
  def test_render_menu_node_with_children
103
    User.current = User.find(2)
104

  
105
    parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
106
                                                     '/test',
107
                                                     {
108
                                                       :children => Proc.new {|p|
109
                                                         children = []
110
                                                         3.times do |time|
111
                                                           children << Redmine::MenuManager::MenuItem.new("test_child_#{time}",
112
                                                                                                             {:controller => 'issues', :action => 'index'},
113
                                                                                                             {})
114
                                                         end
115
                                                         children
116
                                                       }
117
                                                     })
118
    @response.body = render_menu_node(parent_node, Project.find(1))
119

  
120
    assert_select("li") do
121
      assert_select("a.parent-node", "Parent node")
122
      assert_select("ul") do
123
        assert_select("li a.test-child-0", "Test child 0")
124
        assert_select("li a.test-child-1", "Test child 1")
125
        assert_select("li a.test-child-2", "Test child 2")
126
      end
127
    end
128
  end
129

  
130
  def test_render_menu_node_with_nested_items_and_children
131
    User.current = User.find(2)
132

  
133
    parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
134
                                                     '/test',
135
                                                     {
136
                                                       :children => Proc.new {|p|
137
                                                         children = []
138
                                                         3.times do |time|
139
                                                           children << Redmine::MenuManager::MenuItem.new("test_child_#{time}", {:controller => 'issues', :action => 'index'}, {})
140
                                                         end
141
                                                         children
142
                                                       }
143
                                                     })
144

  
145
    parent_node << Redmine::MenuManager::MenuItem.new(:child_node,
146
                                                     '/test',
147
                                                     {
148
                                                       :children => Proc.new {|p|
149
                                                         children = []
150
                                                         6.times do |time|
151
                                                            children << Redmine::MenuManager::MenuItem.new("test_dynamic_child_#{time}", {:controller => 'issues', :action => 'index'}, {})
152
                                                         end
153
                                                         children
154
                                                       }
155
                                                     })
156

  
157
    @response.body = render_menu_node(parent_node, Project.find(1))
158

  
159
    assert_select("li") do
160
      assert_select("a.parent-node", "Parent node")
161
      assert_select("ul") do
162
        assert_select("li a.child-node", "Child node")
163
        assert_select("ul") do
164
          assert_select("li a.test-dynamic-child-0", "Test dynamic child 0")
165
          assert_select("li a.test-dynamic-child-1", "Test dynamic child 1")
166
          assert_select("li a.test-dynamic-child-2", "Test dynamic child 2")
167
          assert_select("li a.test-dynamic-child-3", "Test dynamic child 3")
168
          assert_select("li a.test-dynamic-child-4", "Test dynamic child 4")
169
          assert_select("li a.test-dynamic-child-5", "Test dynamic child 5")
170
        end
171
        assert_select("li a.test-child-0", "Test child 0")
172
        assert_select("li a.test-child-1", "Test child 1")
173
        assert_select("li a.test-child-2", "Test child 2")
174
      end
175
    end
176
  end
177

  
178
  def test_render_menu_node_with_children_without_an_array
179
    parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
180
                                                     '/test',
181
                                                     {
182
                                                       :children => Proc.new {|p| Redmine::MenuManager::MenuItem.new("test_child", "/testing", {})}
183
                                                     })
184

  
185
    assert_raises Redmine::MenuManager::MenuError, ":children must be an array of MenuItems" do
186
      @response.body = render_menu_node(parent_node, Project.find(1))
187
    end
188
  end
189

  
190
  def test_render_menu_node_with_incorrect_children
191
    parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
192
                                                     '/test',
193
                                                     {
194
                                                       :children => Proc.new {|p| ["a string"] }
195
                                                     })
196

  
197
    assert_raises Redmine::MenuManager::MenuError, ":children must be an array of MenuItems" do
198
      @response.body = render_menu_node(parent_node, Project.find(1))
199
    end
200

  
201
  end
202

  
203
  def test_menu_items_for_should_yield_all_items_if_passed_a_block
204
    menu_name = :test_menu_items_for_should_yield_all_items_if_passed_a_block
205
    Redmine::MenuManager.map menu_name do |menu|
206
      menu.push(:a_menu, '/', { })
207
      menu.push(:a_menu_2, '/', { })
208
      menu.push(:a_menu_3, '/', { })
209
    end
210

  
211
    items_yielded = []
212
    menu_items_for(menu_name) do |item|
213
      items_yielded << item
214
    end
215

  
216
    assert_equal 3, items_yielded.size
217
  end
218

  
219
  def test_menu_items_for_should_return_all_items
220
    menu_name = :test_menu_items_for_should_return_all_items
221
    Redmine::MenuManager.map menu_name do |menu|
222
      menu.push(:a_menu, '/', { })
223
      menu.push(:a_menu_2, '/', { })
224
      menu.push(:a_menu_3, '/', { })
225
    end
226

  
227
    items = menu_items_for(menu_name)
228
    assert_equal 3, items.size
229
  end
230

  
231
  def test_menu_items_for_should_skip_unallowed_items_on_a_project
232
    menu_name = :test_menu_items_for_should_skip_unallowed_items_on_a_project
233
    Redmine::MenuManager.map menu_name do |menu|
234
      menu.push(:a_menu, {:controller => 'issues', :action => 'index' }, { })
235
      menu.push(:a_menu_2, {:controller => 'issues', :action => 'index' }, { })
236
      menu.push(:unallowed, {:controller => 'issues', :action => 'unallowed' }, { })
237
    end
238

  
239
    User.current = User.find(2)
240

  
241
    items = menu_items_for(menu_name, Project.find(1))
242
    assert_equal 2, items.size
243
  end
244

  
245
  def test_menu_items_for_should_skip_items_that_fail_the_conditions
246
    menu_name = :test_menu_items_for_should_skip_items_that_fail_the_conditions
247
    Redmine::MenuManager.map menu_name do |menu|
248
      menu.push(:a_menu, {:controller => 'issues', :action => 'index' }, { })
249
      menu.push(:unallowed,
250
                {:controller => 'issues', :action => 'index' },
251
                { :if => Proc.new { false }})
252
    end
253

  
254
    User.current = User.find(2)
255

  
256
    items = menu_items_for(menu_name, Project.find(1))
257
    assert_equal 1, items.size
258
  end
259

  
260
end
.svn/pristine/01/0154cdd03545376764b58ded20a14138238e65d0.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
require File.expand_path('../../../../test_helper', __FILE__)
19

  
20
class Redmine::Hook::ManagerTest < ActionView::TestCase
21
  fixtures :projects, :users, :members, :member_roles, :roles,
22
           :groups_users,
23
           :trackers, :projects_trackers,
24
           :enabled_modules,
25
           :versions,
26
           :issue_statuses, :issue_categories, :issue_relations,
27
           :enumerations,
28
           :issues
29

  
30
  # Some hooks that are manually registered in these tests
31
  class TestHook < Redmine::Hook::ViewListener; end
32

  
33
  class TestHook1 < TestHook
34
    def view_layouts_base_html_head(context)
35
      'Test hook 1 listener.'
36
    end
37
  end
38

  
39
  class TestHook2 < TestHook
40
    def view_layouts_base_html_head(context)
41
      'Test hook 2 listener.'
42
    end
43
  end
44

  
45
  class TestHook3 < TestHook
46
    def view_layouts_base_html_head(context)
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff