Revision 1297:0a574315af3e .svn/pristine/73

View differences:

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

  
20
module SettingsHelper
21
  def administration_settings_tabs
22
    tabs = [{:name => 'general', :partial => 'settings/general', :label => :label_general},
23
            {:name => 'display', :partial => 'settings/display', :label => :label_display},
24
            {:name => 'authentication', :partial => 'settings/authentication', :label => :label_authentication},
25
            {:name => 'projects', :partial => 'settings/projects', :label => :label_project_plural},
26
            {:name => 'issues', :partial => 'settings/issues', :label => :label_issue_tracking},
27
            {:name => 'notifications', :partial => 'settings/notifications', :label => :field_mail_notification},
28
            {:name => 'mail_handler', :partial => 'settings/mail_handler', :label => :label_incoming_emails},
29
            {:name => 'repositories', :partial => 'settings/repositories', :label => :label_repository_plural}
30
            ]
31
  end
32

  
33
  def setting_select(setting, choices, options={})
34
    if blank_text = options.delete(:blank)
35
      choices = [[blank_text.is_a?(Symbol) ? l(blank_text) : blank_text, '']] + choices
36
    end
37
    setting_label(setting, options).html_safe +
38
      select_tag("settings[#{setting}]",
39
                 options_for_select(choices, Setting.send(setting).to_s),
40
                 options).html_safe
41
  end
42

  
43
  def setting_multiselect(setting, choices, options={})
44
    setting_values = Setting.send(setting)
45
    setting_values = [] unless setting_values.is_a?(Array)
46

  
47
    content_tag("label", l(options[:label] || "setting_#{setting}")) +
48
      hidden_field_tag("settings[#{setting}][]", '').html_safe +
49
      choices.collect do |choice|
50
        text, value = (choice.is_a?(Array) ? choice : [choice, choice])
51
        content_tag(
52
          'label',
53
          check_box_tag(
54
             "settings[#{setting}][]",
55
             value,
56
             Setting.send(setting).include?(value),
57
             :id => nil
58
           ) + text.to_s,
59
          :class => (options[:inline] ? 'inline' : 'block')
60
         )
61
      end.join.html_safe
62
  end
63

  
64
  def setting_text_field(setting, options={})
65
    setting_label(setting, options).html_safe +
66
      text_field_tag("settings[#{setting}]", Setting.send(setting), options).html_safe
67
  end
68

  
69
  def setting_text_area(setting, options={})
70
    setting_label(setting, options).html_safe +
71
      text_area_tag("settings[#{setting}]", Setting.send(setting), options).html_safe
72
  end
73

  
74
  def setting_check_box(setting, options={})
75
    setting_label(setting, options).html_safe +
76
      hidden_field_tag("settings[#{setting}]", 0, :id => nil).html_safe +
77
        check_box_tag("settings[#{setting}]", 1, Setting.send("#{setting}?"), options).html_safe
78
  end
79

  
80
  def setting_label(setting, options={})
81
    label = options.delete(:label)
82
    label != false ? label_tag("settings_#{setting}", l(label || "setting_#{setting}")).html_safe : ''
83
  end
84

  
85
  # Renders a notification field for a Redmine::Notifiable option
86
  def notification_field(notifiable)
87
    return content_tag(:label,
88
                       check_box_tag('settings[notified_events][]',
89
                                     notifiable.name,
90
                                     Setting.notified_events.include?(notifiable.name), :id => nil).html_safe +
91
                         l_or_humanize(notifiable.name, :prefix => 'label_').html_safe,
92
                       :class => notifiable.parent.present? ? "parent" : '').html_safe
93
  end
94

  
95
  def cross_project_subtasks_options
96
    options = [
97
      [:label_disabled, ''],
98
      [:label_cross_project_system, 'system'],
99
      [:label_cross_project_tree, 'tree'],
100
      [:label_cross_project_hierarchy, 'hierarchy'],
101
      [:label_cross_project_descendants, 'descendants']
102
    ]
103

  
104
    options.map {|label, value| [l(label), value.to_s]}
105
  end
106
end
.svn/pristine/73/733ef5f2e7612d0ddf7c032e9fce87a523e4ff33.svn-base
1
require File.expand_path('../../test_helper', __FILE__)
2
require 'issue_statuses_controller'
3

  
4
# Re-raise errors caught by the controller.
5
class IssueStatusesController; def rescue_action(e) raise e end; end
6

  
7

  
8
class IssueStatusesControllerTest < ActionController::TestCase
9
  fixtures :issue_statuses, :issues, :users
10

  
11
  def setup
12
    @controller = IssueStatusesController.new
13
    @request    = ActionController::TestRequest.new
14
    @response   = ActionController::TestResponse.new
15
    User.current = nil
16
    @request.session[:user_id] = 1 # admin
17
  end
18

  
19
  def test_index
20
    get :index
21
    assert_response :success
22
    assert_template 'index'
23
  end
24
  
25
  def test_index_by_anonymous_should_redirect_to_login_form
26
    @request.session[:user_id] = nil
27
    get :index
28
    assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fissue_statuses'
29
  end
30
  
31
  def test_index_by_user_should_respond_with_406
32
    @request.session[:user_id] = 2
33
    get :index
34
    assert_response 406
35
  end
36

  
37
  def test_new
38
    get :new
39
    assert_response :success
40
    assert_template 'new'
41
  end
42

  
43
  def test_create
44
    assert_difference 'IssueStatus.count' do
45
      post :create, :issue_status => {:name => 'New status'}
46
    end
47
    assert_redirected_to :action => 'index'
48
    status = IssueStatus.find(:first, :order => 'id DESC')
49
    assert_equal 'New status', status.name
50
  end
51

  
52
  def test_create_with_failure
53
    post :create, :issue_status => {:name => ''}
54
    assert_response :success
55
    assert_template 'new'
56
    assert_error_tag :content => /name can&#x27;t be blank/i
57
  end
58

  
59
  def test_edit
60
    get :edit, :id => '3'
61
    assert_response :success
62
    assert_template 'edit'
63
  end
64

  
65
  def test_update
66
    put :update, :id => '3', :issue_status => {:name => 'Renamed status'}
67
    assert_redirected_to :action => 'index'
68
    status = IssueStatus.find(3)
69
    assert_equal 'Renamed status', status.name
70
  end
71

  
72
  def test_update_with_failure
73
    put :update, :id => '3', :issue_status => {:name => ''}
74
    assert_response :success
75
    assert_template 'edit'
76
    assert_error_tag :content => /name can&#x27;t be blank/i
77
  end
78

  
79
  def test_destroy
80
    Issue.delete_all("status_id = 1")
81

  
82
    assert_difference 'IssueStatus.count', -1 do
83
      delete :destroy, :id => '1'
84
    end
85
    assert_redirected_to :action => 'index'
86
    assert_nil IssueStatus.find_by_id(1)
87
  end
88

  
89
  def test_destroy_should_block_if_status_in_use
90
    assert_not_nil Issue.find_by_status_id(1)
91

  
92
    assert_no_difference 'IssueStatus.count' do
93
      delete :destroy, :id => '1'
94
    end
95
    assert_redirected_to :action => 'index'
96
    assert_not_nil IssueStatus.find_by_id(1)
97
  end
98

  
99
  def test_update_issue_done_ratio_with_issue_done_ratio_set_to_issue_field
100
    with_settings :issue_done_ratio => 'issue_field' do
101
      post :update_issue_done_ratio
102
      assert_match /not updated/, flash[:error].to_s
103
      assert_redirected_to '/issue_statuses'
104
    end
105
  end
106

  
107
  def test_update_issue_done_ratio_with_issue_done_ratio_set_to_issue_status
108
    with_settings :issue_done_ratio => 'issue_status' do
109
      post :update_issue_done_ratio
110
      assert_match /Issue done ratios updated/, flash[:notice].to_s
111
      assert_redirected_to '/issue_statuses'
112
    end
113
  end
114
end
.svn/pristine/73/73413db85b6306a4b47ad7eb7dece1c50a1f9330.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2012  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
require 'digest/md5'
20

  
21
class Redmine::WikiFormatting::TextileFormatterTest < ActionView::TestCase
22

  
23
  def setup
24
    @formatter = Redmine::WikiFormatting::Textile::Formatter
25
  end
26

  
27
  MODIFIERS = {
28
    "*" => 'strong', # bold
29
    "_" => 'em',     # italic
30
    "+" => 'ins',    # underline
31
    "-" => 'del',    # deleted
32
    "^" => 'sup',    # superscript
33
    "~" => 'sub'     # subscript
34
  }
35

  
36
  def test_modifiers
37
    assert_html_output(
38
      '*bold*'                => '<strong>bold</strong>',
39
      'before *bold*'         => 'before <strong>bold</strong>',
40
      '*bold* after'          => '<strong>bold</strong> after',
41
      '*two words*'           => '<strong>two words</strong>',
42
      '*two*words*'           => '<strong>two*words</strong>',
43
      '*two * words*'         => '<strong>two * words</strong>',
44
      '*two* *words*'         => '<strong>two</strong> <strong>words</strong>',
45
      '*(two)* *(words)*'     => '<strong>(two)</strong> <strong>(words)</strong>',
46
      # with class
47
      '*(foo)two words*'      => '<strong class="foo">two words</strong>'
48
    )
49
  end
50

  
51
  def test_modifiers_combination
52
    MODIFIERS.each do |m1, tag1|
53
      MODIFIERS.each do |m2, tag2|
54
        next if m1 == m2
55
        text = "#{m2}#{m1}Phrase modifiers#{m1}#{m2}"
56
        html = "<#{tag2}><#{tag1}>Phrase modifiers</#{tag1}></#{tag2}>"
57
        assert_html_output text => html
58
      end
59
    end
60
  end
61

  
62
  def test_styles
63
    # single style
64
    assert_html_output({
65
      'p{color:red}. text'           => '<p style="color:red;">text</p>',
66
      'p{color:red;}. text'          => '<p style="color:red;">text</p>',
67
      'p{color: red}. text'          => '<p style="color: red;">text</p>',
68
      'p{color:#f00}. text'          => '<p style="color:#f00;">text</p>',
69
      'p{color:#ff0000}. text'       => '<p style="color:#ff0000;">text</p>',
70
      'p{border:10px}. text'         => '<p style="border:10px;">text</p>',
71
      'p{border:10}. text'           => '<p style="border:10;">text</p>',
72
      'p{border:10%}. text'          => '<p style="border:10%;">text</p>',
73
      'p{border:10em}. text'         => '<p style="border:10em;">text</p>',
74
      'p{border:1.5em}. text'        => '<p style="border:1.5em;">text</p>',
75
      'p{border-left:1px}. text'     => '<p style="border-left:1px;">text</p>',
76
      'p{border-right:1px}. text'    => '<p style="border-right:1px;">text</p>',
77
      'p{border-top:1px}. text'      => '<p style="border-top:1px;">text</p>',
78
      'p{border-bottom:1px}. text'   => '<p style="border-bottom:1px;">text</p>',
79
      }, false)
80

  
81
    # multiple styles
82
    assert_html_output({
83
      'p{color:red; border-top:1px}. text'   => '<p style="color:red;border-top:1px;">text</p>',
84
      'p{color:red ; border-top:1px}. text'  => '<p style="color:red;border-top:1px;">text</p>',
85
      'p{color:red;border-top:1px}. text'    => '<p style="color:red;border-top:1px;">text</p>',
86
      }, false)
87

  
88
    # styles with multiple values
89
    assert_html_output({
90
      'p{border:1px solid red;}. text'             => '<p style="border:1px solid red;">text</p>',
91
      'p{border-top-left-radius: 10px 5px;}. text' => '<p style="border-top-left-radius: 10px 5px;">text</p>',
92
      }, false)
93
  end
94

  
95
  def test_invalid_styles_should_be_filtered
96
    assert_html_output({
97
      'p{invalid}. text'                     => '<p>text</p>',
98
      'p{invalid:red}. text'                 => '<p>text</p>',
99
      'p{color:(red)}. text'                 => '<p>text</p>',
100
      'p{color:red;invalid:blue}. text'      => '<p style="color:red;">text</p>',
101
      'p{invalid:blue;color:red}. text'      => '<p style="color:red;">text</p>',
102
      'p{color:"}. text'                     => '<p>p{color:"}. text</p>',
103
      }, false)
104
  end
105

  
106
  def test_inline_code
107
    assert_html_output(
108
      'this is @some code@'      => 'this is <code>some code</code>',
109
      '@<Location /redmine>@'    => '<code>&lt;Location /redmine&gt;</code>'
110
    )
111
  end
112

  
113
  def test_nested_lists
114
    raw = <<-RAW
115
# Item 1
116
# Item 2
117
** Item 2a
118
** Item 2b
119
# Item 3
120
** Item 3a
121
RAW
122

  
123
    expected = <<-EXPECTED
124
<ol>
125
  <li>Item 1</li>
126
  <li>Item 2
127
    <ul>
128
      <li>Item 2a</li>
129
      <li>Item 2b</li>
130
    </ul>
131
  </li>
132
  <li>Item 3
133
    <ul>
134
      <li>Item 3a</li>
135
    </ul>
136
  </li>
137
</ol>
138
EXPECTED
139

  
140
    assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
141
  end
142

  
143
  def test_escaping
144
    assert_html_output(
145
      'this is a <script>'      => 'this is a &lt;script&gt;'
146
    )
147
  end
148

  
149
  def test_use_of_backslashes_followed_by_numbers_in_headers
150
    assert_html_output({
151
      'h1. 2009\02\09'      => '<h1>2009\02\09</h1>'
152
    }, false)
153
  end
154

  
155
  def test_double_dashes_should_not_strikethrough
156
    assert_html_output(
157
      'double -- dashes -- test'  => 'double -- dashes -- test',
158
      'double -- *dashes* -- test'  => 'double -- <strong>dashes</strong> -- test'
159
    )
160
  end
161

  
162
  def test_acronyms
163
    assert_html_output(
164
      'this is an acronym: GPL(General Public License)' => 'this is an acronym: <acronym title="General Public License">GPL</acronym>',
165
      '2 letters JP(Jean-Philippe) acronym' => '2 letters <acronym title="Jean-Philippe">JP</acronym> acronym',
166
      'GPL(This is a double-quoted "title")' => '<acronym title="This is a double-quoted &quot;title&quot;">GPL</acronym>'
167
    )
168
  end
169

  
170
  def test_blockquote
171
    # orig raw text
172
    raw = <<-RAW
173
John said:
174
> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
175
> Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
176
> * Donec odio lorem,
177
> * sagittis ac,
178
> * malesuada in,
179
> * adipiscing eu, dolor.
180
>
181
> >Nulla varius pulvinar diam. Proin id arcu id lorem scelerisque condimentum. Proin vehicula turpis vitae lacus.
182
> Proin a tellus. Nam vel neque.
183

  
184
He's right.
185
RAW
186

  
187
    # expected html
188
    expected = <<-EXPECTED
189
<p>John said:</p>
190
<blockquote>
191
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.<br />
192
Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
193
<ul>
194
  <li>Donec odio lorem,</li>
195
  <li>sagittis ac,</li>
196
  <li>malesuada in,</li>
197
  <li>adipiscing eu, dolor.</li>
198
</ul>
199
<blockquote>
200
<p>Nulla varius pulvinar diam. Proin id arcu id lorem scelerisque condimentum. Proin vehicula turpis vitae lacus.</p>
201
</blockquote>
202
<p>Proin a tellus. Nam vel neque.</p>
203
</blockquote>
204
<p>He's right.</p>
205
EXPECTED
206

  
207
    assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
208
  end
209

  
210
  def test_table
211
    raw = <<-RAW
212
This is a table with empty cells:
213

  
214
|cell11|cell12||
215
|cell21||cell23|
216
|cell31|cell32|cell33|
217
RAW
218

  
219
    expected = <<-EXPECTED
220
<p>This is a table with empty cells:</p>
221

  
222
<table>
223
  <tr><td>cell11</td><td>cell12</td><td></td></tr>
224
  <tr><td>cell21</td><td></td><td>cell23</td></tr>
225
  <tr><td>cell31</td><td>cell32</td><td>cell33</td></tr>
226
</table>
227
EXPECTED
228

  
229
    assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
230
  end
231

  
232
  def test_table_with_line_breaks
233
    raw = <<-RAW
234
This is a table with line breaks:
235

  
236
|cell11
237
continued|cell12||
238
|-cell21-||cell23
239
cell23 line2
240
cell23 *line3*|
241
|cell31|cell32
242
cell32 line2|cell33|
243

  
244
RAW
245

  
246
    expected = <<-EXPECTED
247
<p>This is a table with line breaks:</p>
248

  
249
<table>
250
  <tr>
251
    <td>cell11<br />continued</td>
252
    <td>cell12</td>
253
    <td></td>
254
  </tr>
255
  <tr>
256
    <td><del>cell21</del></td>
257
    <td></td>
258
    <td>cell23<br/>cell23 line2<br/>cell23 <strong>line3</strong></td>
259
  </tr>
260
  <tr>
261
    <td>cell31</td>
262
    <td>cell32<br/>cell32 line2</td>
263
    <td>cell33</td>
264
  </tr>
265
</table>
266
EXPECTED
267

  
268
    assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
269
  end
270

  
271
  def test_textile_should_not_mangle_brackets
272
    assert_equal '<p>[msg1][msg2]</p>', to_html('[msg1][msg2]')
273
  end
274

  
275
  def test_textile_should_escape_image_urls
276
    # this is onclick="alert('XSS');" in encoded form
277
    raw = '!/images/comment.png"onclick=&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x27;&#x58;&#x53;&#x53;&#x27;&#x29;;&#x22;!'
278
    expected = '<p><img src="/images/comment.png&quot;onclick=&amp;#x61;&amp;#x6c;&amp;#x65;&amp;#x72;&amp;#x74;&amp;#x28;&amp;#x27;&amp;#x58;&amp;#x53;&amp;#x53;&amp;#x27;&amp;#x29;;&amp;#x22;" alt="" /></p>'
279
    assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
280
  end
281
  
282
  
283
  STR_WITHOUT_PRE = [
284
  # 0
285
"h1. Title
286

  
287
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.",
288
  # 1
289
"h2. Heading 2
290

  
291
Maecenas sed elit sit amet mi accumsan vestibulum non nec velit. Proin porta tincidunt lorem, consequat rhoncus dolor fermentum in.
292

  
293
Cras ipsum felis, ultrices at porttitor vel, faucibus eu nunc.",
294
  # 2
295
"h2. Heading 2
296

  
297
Morbi facilisis accumsan orci non pharetra.
298

  
299
h3. Heading 3
300

  
301
Nulla nunc nisi, egestas in ornare vel, posuere ac libero.",
302
  # 3
303
"h3. Heading 3
304

  
305
Praesent eget turpis nibh, a lacinia nulla.",
306
  # 4
307
"h2. Heading 2
308

  
309
Ut rhoncus elementum adipiscing."]
310

  
311
  TEXT_WITHOUT_PRE = STR_WITHOUT_PRE.join("\n\n").freeze
312
  
313
  def test_get_section_should_return_the_requested_section_and_its_hash
314
    assert_section_with_hash STR_WITHOUT_PRE[1], TEXT_WITHOUT_PRE, 2
315
    assert_section_with_hash STR_WITHOUT_PRE[2..3].join("\n\n"), TEXT_WITHOUT_PRE, 3
316
    assert_section_with_hash STR_WITHOUT_PRE[3], TEXT_WITHOUT_PRE, 5
317
    assert_section_with_hash STR_WITHOUT_PRE[4], TEXT_WITHOUT_PRE, 6
318
    
319
    assert_section_with_hash '', TEXT_WITHOUT_PRE, 0
320
    assert_section_with_hash '', TEXT_WITHOUT_PRE, 10
321
  end
322
  
323
  def test_update_section_should_update_the_requested_section
324
    replacement = "New text"
325
    
326
    assert_equal [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(2, replacement)
327
    assert_equal [STR_WITHOUT_PRE[0..1], replacement, STR_WITHOUT_PRE[4]].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(3, replacement)
328
    assert_equal [STR_WITHOUT_PRE[0..2], replacement, STR_WITHOUT_PRE[4]].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(5, replacement)
329
    assert_equal [STR_WITHOUT_PRE[0..3], replacement].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(6, replacement)
330
    
331
    assert_equal TEXT_WITHOUT_PRE, @formatter.new(TEXT_WITHOUT_PRE).update_section(0, replacement)
332
    assert_equal TEXT_WITHOUT_PRE, @formatter.new(TEXT_WITHOUT_PRE).update_section(10, replacement)
333
  end
334
  
335
  def test_update_section_with_hash_should_update_the_requested_section
336
    replacement = "New text"
337
    
338
    assert_equal [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].flatten.join("\n\n"),
339
      @formatter.new(TEXT_WITHOUT_PRE).update_section(2, replacement, Digest::MD5.hexdigest(STR_WITHOUT_PRE[1]))
340
  end
341
  
342
  def test_update_section_with_wrong_hash_should_raise_an_error
343
    assert_raise Redmine::WikiFormatting::StaleSectionError do
344
      @formatter.new(TEXT_WITHOUT_PRE).update_section(2, "New text", Digest::MD5.hexdigest("Old text"))
345
    end
346
  end
347

  
348
  STR_WITH_PRE = [
349
  # 0
350
"h1. Title
351

  
352
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.",
353
  # 1
354
"h2. Heading 2
355

  
356
<pre><code class=\"ruby\">
357
  def foo
358
  end
359
</code></pre>
360

  
361
<pre><code><pre><code class=\"ruby\">
362
  Place your code here.
363
</code></pre>
364
</code></pre>
365

  
366
Morbi facilisis accumsan orci non pharetra.
367

  
368
<pre>
369
Pre Content:
370

  
371
h2. Inside pre
372

  
373
<tag> inside pre block
374

  
375
Morbi facilisis accumsan orci non pharetra.
376
</pre>",
377
  # 2
378
"h3. Heading 3
379

  
380
Nulla nunc nisi, egestas in ornare vel, posuere ac libero."]
381

  
382
  def test_get_section_should_ignore_pre_content
383
    text = STR_WITH_PRE.join("\n\n")
384

  
385
    assert_section_with_hash STR_WITH_PRE[1..2].join("\n\n"), text, 2
386
    assert_section_with_hash STR_WITH_PRE[2], text, 3
387
  end
388

  
389
  def test_update_section_should_not_escape_pre_content_outside_section
390
    text = STR_WITH_PRE.join("\n\n")
391
    replacement = "New text"
392
    
393
    assert_equal [STR_WITH_PRE[0..1], "New text"].flatten.join("\n\n"),
394
      @formatter.new(text).update_section(3, replacement)
395
  end
396

  
397
  def test_get_section_should_support_lines_with_spaces_before_heading
398
    # the lines after Content 2 and Heading 4 contain a space
399
    text = <<-STR
400
h1. Heading 1
401

  
402
Content 1
403

  
404
h1. Heading 2
405

  
406
Content 2
407
 
408
h1. Heading 3
409

  
410
Content 3
411

  
412
h1. Heading 4
413
 
414
Content 4
415
STR
416

  
417
    [1, 2, 3, 4].each do |index|
418
      assert_match /\Ah1. Heading #{index}.+Content #{index}/m, @formatter.new(text).get_section(index).first
419
    end
420
  end
421

  
422
  def test_get_section_should_support_headings_starting_with_a_tab
423
    text = <<-STR
424
h1.\tHeading 1
425

  
426
Content 1
427

  
428
h1. Heading 2
429

  
430
Content 2
431
STR
432

  
433
    assert_match /\Ah1.\tHeading 1\s+Content 1\z/, @formatter.new(text).get_section(1).first
434
  end
435

  
436
  private
437

  
438
  def assert_html_output(to_test, expect_paragraph = true)
439
    to_test.each do |text, expected|
440
      assert_equal(( expect_paragraph ? "<p>#{expected}</p>" : expected ), @formatter.new(text).to_html, "Formatting the following text failed:\n===\n#{text}\n===\n")
441
    end
442
  end
443

  
444
  def to_html(text)
445
    @formatter.new(text).to_html
446
  end
447
  
448
  def assert_section_with_hash(expected, text, index)
449
    result = @formatter.new(text).get_section(index)
450
    
451
    assert_kind_of Array, result
452
    assert_equal 2, result.size
453
    assert_equal expected, result.first, "section content did not match"
454
    assert_equal Digest::MD5.hexdigest(expected), result.last, "section hash did not match"
455
  end
456
end
.svn/pristine/73/735b0fd3b5409c9a5e4b21cbea9f8fc0ee3ea376.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2012  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
module Redmine
19
  module WikiFormatting
20
    module Textile
21
      module Helper
22
        def wikitoolbar_for(field_id)
23
          heads_for_wiki_formatter
24
          # Is there a simple way to link to a public resource?
25
          url = "#{Redmine::Utils.relative_url_root}/help/wiki_syntax.html"
26
          help_link = link_to(l(:setting_text_formatting), url,
27
            :onclick => "window.open(\"#{ url }\", \"\", \"resizable=yes, location=no, width=300, height=640, menubar=no, status=no, scrollbars=yes\"); return false;")
28

  
29
          javascript_tag("var wikiToolbar = new jsToolBar(document.getElementById('#{field_id}')); wikiToolbar.setHelpLink('#{escape_javascript help_link}'); wikiToolbar.draw();")
30
        end
31

  
32
        def initial_page_content(page)
33
          "h1. #{@page.pretty_title}"
34
        end
35

  
36
        def heads_for_wiki_formatter
37
          unless @heads_for_wiki_formatter_included
38
            content_for :header_tags do
39
              javascript_include_tag('jstoolbar/jstoolbar-textile.min') +
40
              javascript_include_tag("jstoolbar/lang/jstoolbar-#{current_language.to_s.downcase}") +
41
              stylesheet_link_tag('jstoolbar')
42
            end
43
            @heads_for_wiki_formatter_included = true
44
          end
45
        end
46
      end
47
    end
48
  end
49
end
.svn/pristine/73/739ef0925b98594bbd1e537e9b5096bdd12d62a3.svn-base
1
<div class="contextual">
2
  <% if User.current.allowed_to?(:add_subprojects, @project) %>
3
    <%= link_to l(:label_subproject_new), {:controller => 'projects', :action => 'new', :parent_id => @project}, :class => 'icon icon-add' %>
4
  <% end %>
5
  <% if User.current.allowed_to?(:close_project, @project) %>
6
    <% if @project.active? %>
7
      <%= link_to l(:button_close), close_project_path(@project), :data => {:confirm => l(:text_are_you_sure)}, :method => :post, :class => 'icon icon-lock' %>
8
    <% else %>
9
      <%= link_to l(:button_reopen), reopen_project_path(@project), :data => {:confirm => l(:text_are_you_sure)}, :method => :post, :class => 'icon icon-unlock' %>
10
    <% end %>
11
  <% end %>
12
</div>
13

  
14
<h2><%=l(:label_overview)%></h2>
15

  
16
<% unless @project.active? %>
17
  <p class="warning"><span class="icon icon-lock"><%= l(:text_project_closed) %></span></p>
18
<% end %>
19

  
20
<div class="splitcontentleft">
21
  <% if @project.description.present? %>
22
  <div class="wiki">
23
    <%= textilizable @project.description %>
24
  </div>
25
  <% end %>
26
  <ul>
27
  <% unless @project.homepage.blank? %>
28
    <li><%=l(:field_homepage)%>: <%= link_to h(@project.homepage), @project.homepage %></li>
29
  <% end %>
30
  <% if @subprojects.any? %>
31
    <li><%=l(:label_subproject_plural)%>:
32
      <%= @subprojects.collect{|p| link_to(h(p), :action => 'show', :id => p)}.join(", ").html_safe %></li>
33
  <% end %>
34
  <% @project.visible_custom_field_values.each do |custom_value| %>
35
  <% if !custom_value.value.blank? %>
36
     <li><%=h custom_value.custom_field.name %>: <%=h show_value(custom_value) %></li>
37
  <% end %>
38
  <% end %>
39
  </ul>
40

  
41
  <% if User.current.allowed_to?(:view_issues, @project) %>
42
  <div class="issues box">
43
    <h3><%=l(:label_issue_tracking)%></h3>
44
    <ul>
45
    <% for tracker in @trackers %>
46
      <li><%= link_to h(tracker.name), :controller => 'issues', :action => 'index', :project_id => @project,
47
                                                :set_filter => 1,
48
                                                "tracker_id" => tracker.id %>:
49
          <%= l(:label_x_open_issues_abbr_on_total, :count => @open_issues_by_tracker[tracker].to_i,
50
                                                    :total => @total_issues_by_tracker[tracker].to_i) %>
51
      </li>
52
    <% end %>
53
    </ul>
54
    <p>
55
      <%= link_to l(:label_issue_view_all), :controller => 'issues', :action => 'index', :project_id => @project, :set_filter => 1 %>
56
      <% if User.current.allowed_to?(:view_calendar, @project, :global => true) %>
57
        | <%= link_to(l(:label_calendar), :controller => 'calendars', :action => 'show', :project_id => @project) %>
58
      <% end %>
59
      <% if User.current.allowed_to?(:view_gantt, @project, :global => true) %>
60
        | <%= link_to(l(:label_gantt), :controller => 'gantts', :action => 'show', :project_id => @project) %>
61
      <% end %>
62
    </p>
63
  </div>
64
  <% end %>
65
  <%= call_hook(:view_projects_show_left, :project => @project) %>
66
</div>
67

  
68
<div class="splitcontentright">
69
  <%= render :partial => 'members_box' %>
70

  
71
  <% if @news.any? && authorize_for('news', 'index') %>
72
  <div class="news box">
73
    <h3><%=l(:label_news_latest)%></h3>
74
    <%= render :partial => 'news/news', :collection => @news %>
75
    <p><%= link_to l(:label_news_view_all), :controller => 'news', :action => 'index', :project_id => @project %></p>
76
  </div>
77
  <% end %>
78
  <%= call_hook(:view_projects_show_right, :project => @project) %>
79
</div>
80

  
81
<% content_for :sidebar do %>
82
    <% if @total_hours.present? %>
83
    <h3><%= l(:label_spent_time) %></h3>
84
    <p><span class="icon icon-time"><%= l_hours(@total_hours) %></span></p>
85
    <p>
86
    <% if User.current.allowed_to?(:log_time, @project) %>
87
      <%= link_to l(:button_log_time), new_project_time_entry_path(@project) %> |
88
    <% end %>
89
    <%= link_to(l(:label_details), project_time_entries_path(@project)) %> |
90
    <%= link_to(l(:label_report), report_project_time_entries_path(@project)) %></p>
91
    <% end %>
92
    <%= call_hook(:view_projects_show_sidebar_bottom, :project => @project) %>
93
<% end %>
94

  
95
<% content_for :header_tags do %>
96
<%= auto_discovery_link_tag(:atom, {:controller => 'activities', :action => 'index', :id => @project, :format => 'atom', :key => User.current.rss_key}) %>
97
<% end %>
98

  
99
<% html_title(l(:label_overview)) -%>

Also available in: Unified diff