wagn 1.14.1 → 1.14.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.tm_properties +2 -1
  3. data/VERSION +1 -1
  4. data/app/controllers/card_controller.rb +4 -3
  5. data/db/bootstrap/card_acts.yml +1 -1
  6. data/db/bootstrap/cards.yml +1028 -1028
  7. data/db/migrate_core_cards/20140629222005_add_email_cards.rb +2 -25
  8. data/db/migrate_core_cards/20141204061304_watchers_to_following.rb +38 -0
  9. data/db/version_core_cards.txt +1 -1
  10. data/features/history.feature +21 -0
  11. data/features/step_definitions/history_steps.rb +3 -0
  12. data/features/step_definitions/wagn_steps.rb +10 -1
  13. data/lib/card/act.rb +2 -2
  14. data/lib/card/action.rb +9 -9
  15. data/lib/card/diff.rb +370 -211
  16. data/lib/card/exceptions.rb +2 -0
  17. data/lib/card/format.rb +5 -3
  18. data/lib/card/query.rb +4 -4
  19. data/lib/card/query/card_spec.rb +69 -51
  20. data/lib/card/set.rb +3 -2
  21. data/lib/wagn.rb +15 -3
  22. data/lib/wagn/all.rb +1 -3
  23. data/lib/wagn/application.rb +10 -1
  24. data/lib/wagn/generators/wagn/templates/Gemfile +6 -1
  25. data/lib/wagn/log.rb +69 -0
  26. data/lib/wagn/tasks/wagn.rake +1 -1
  27. data/mod/01_core/set/all/collection.rb +8 -5
  28. data/mod/01_core/set/all/content.rb +1 -1
  29. data/mod/01_core/set/all/fetch.rb +34 -32
  30. data/mod/01_core/set/all/notify.rb +2 -2
  31. data/mod/01_core/set/all/phases.rb +5 -0
  32. data/mod/01_core/set/all/trash.rb +1 -1
  33. data/mod/02_basic_types/set/type/pointer.rb +4 -0
  34. data/mod/03_machines/set/type/coffee_script.rb +10 -0
  35. data/mod/03_machines/set/type/css.rb +9 -0
  36. data/mod/03_machines/set/type/java_script.rb +5 -0
  37. data/mod/03_machines/set/type/scss.rb +8 -2
  38. data/mod/05_standard/set/all/history.rb +10 -1
  39. data/mod/05_standard/set/type/html.rb +4 -0
  40. data/mod/05_standard/spec/set/all/base_spec.rb +2 -0
  41. data/mod/05_standard/spec/set/all/history_spec.rb +12 -0
  42. data/mod/06_email/set/all/email_html.rb +0 -4
  43. data/mod/06_email/set/type/email_template.rb +6 -2
  44. data/spec/lib/card/diff_spec.rb +207 -107
  45. data/spec/lib/card/query_spec.rb +14 -13
  46. data/test/fixtures/card_actions.yml +21 -0
  47. data/test/fixtures/card_acts.yml +103 -85
  48. data/test/fixtures/card_changes.yml +53 -23
  49. data/test/fixtures/cards.yml +1349 -1331
  50. data/test/seed.rb +5 -1
  51. metadata +8 -3
  52. data/lib/wagn/config/initializers/airbrake.rb +0 -9
@@ -93,7 +93,7 @@ namespace :wagn do
93
93
  desc 'insert existing card migrations into schema_migrations_cards to avoid re-migrating'
94
94
  task :assume_card_migrations do
95
95
  Wagn::Migration.schema_mode :core_cards do
96
- ActiveRecord::Schema.assume_migrated_upto_version Wagn::Version.schema(:core_cards), Wagn::Migration.paths(:core_cards)
96
+ ActiveRecord::Schema.assume_migrated_upto_version Wagn::Version.schema(:core_cards), Wagn::Migration.paths( :core_cards )
97
97
  end
98
98
  end
99
99
 
@@ -1,11 +1,14 @@
1
1
 
2
2
  module ClassMethods
3
3
  def search spec
4
- results = ::Card::Query.new(spec).run
5
- if block_given? and Array===results
6
- results.each { |result| yield result }
4
+ query = ::Card::Query.new(spec)
5
+ Wagn.with_logging nil, :search, spec, query.sql.strip do
6
+ results = query.run
7
+ if block_given? and Array===results
8
+ results.each { |result| yield result }
9
+ end
10
+ results
7
11
  end
8
- results
9
12
  end
10
13
 
11
14
  def count_by_wql(spec)
@@ -28,7 +31,7 @@ def item_type
28
31
  end
29
32
 
30
33
  def include_item? cardname
31
- ::Set.new(item_names.map{|name| name.to_name.key}).member? cardname.to_name.key
34
+ item_names.map{|name| name.to_name.key}.member? cardname.to_name.key
32
35
  end
33
36
 
34
37
  def extended_item_cards context = nil
@@ -24,7 +24,7 @@ def chunk_list #override to customize by set
24
24
  end
25
25
 
26
26
  def last_change_on(field, opts={})
27
- where_sql = 'card_actions.card_id = :card_id AND field = :field AND (draft = 0 OR draft IS NULL)'
27
+ where_sql = 'card_actions.card_id = :card_id AND field = :field AND (draft is false OR draft IS NULL)'
28
28
  where_sql += if opts[:before]
29
29
  'AND card_action_id < :action_id'
30
30
  elsif opts[:not_after]
@@ -21,45 +21,47 @@ module ClassMethods
21
21
 
22
22
 
23
23
  def fetch mark, opts={}
24
- if String === mark
25
- case mark
26
- when /^\~(\d+)$/ # get by id
27
- mark = $1.to_i
28
- when /^\:(\w+)$/ # get by codename
29
- mark = $1.to_sym
24
+ Wagn.with_logging nil, :fetch, mark, opts do
25
+ if String === mark
26
+ case mark
27
+ when /^\~(\d+)$/ # get by id
28
+ mark = $1.to_i
29
+ when /^\:(\w+)$/ # get by codename
30
+ mark = $1.to_sym
31
+ end
30
32
  end
31
- end
32
- mark = Card::Codename[mark] if Symbol === mark # id from codename
33
+ mark = Card::Codename[mark] if Symbol === mark # id from codename
33
34
 
34
- if mark.present?
35
- card, mark, needs_caching = fetch_from_cache_or_db mark, opts # have existing
36
- else
37
- return unless opts[:new]
38
- end
35
+ if mark.present?
36
+ card, mark, needs_caching = fetch_from_cache_or_db mark, opts # have existing
37
+ else
38
+ return unless opts[:new]
39
+ end
39
40
 
40
- if Integer===mark
41
- return if card.nil? || mark.nil?
42
- else
43
- return card.renew(opts) if card and card.eager_renew?(opts)
44
- if !card or card.type_id==-1 && clean_cache_opts?(opts) # new (or improved) card for cache
45
- needs_caching = true
46
- card = new_for_cache mark, opts
47
- end
48
- end
41
+ if Integer===mark
42
+ return if card.nil? || mark.nil?
43
+ else
44
+ return card.renew(opts) if card and card.eager_renew?(opts)
45
+ if !card or card.type_id==-1 && clean_cache_opts?(opts) # new (or improved) card for cache
46
+ needs_caching = true
47
+ card = new_for_cache mark, opts
48
+ end
49
+ end
49
50
 
50
- write_to_cache card if Card.cache && needs_caching
51
+ write_to_cache card if Card.cache && needs_caching
51
52
 
52
- if card.new_card?
53
- if opts[:new]
54
- return card.renew(opts) if !clean_cache_opts? opts
55
- else
56
- return unless !opts[:skip_virtual] && card.virtual?
53
+ if card.new_card?
54
+ if opts[:new]
55
+ return card.renew(opts) if !clean_cache_opts? opts
56
+ else
57
+ return unless !opts[:skip_virtual] && card.virtual?
58
+ end
59
+ card.name = mark.to_s if mark && mark.to_s != card.name
57
60
  end
58
- card.name = mark.to_s if mark && mark.to_s != card.name
59
- end
60
61
 
61
- card.include_set_modules unless opts[:skip_modules]
62
- card
62
+ card.include_set_modules unless opts[:skip_modules]
63
+ card
64
+ end
63
65
  end
64
66
 
65
67
  def fetch_id mark #should optimize this. what if mark is int? or codename?
@@ -77,9 +77,9 @@ event :notify_followers, :after=>:extend, :when=>proc{ |c|
77
77
  end
78
78
  end
79
79
  rescue =>e #this error handling should apply to all extend callback exceptions
80
- Airbrake.notify e if Airbrake.configuration.api_key
81
80
  Rails.logger.info "\nController exception: #{e.message}"
82
- Rails.logger.debug "BT: #{e.backtrace*"\n"}"
81
+ Card::Error.current = e
82
+ notable_exception_raised
83
83
  end
84
84
  end
85
85
 
@@ -116,6 +116,11 @@ def rescue_event e
116
116
  # false
117
117
  end
118
118
 
119
+ event :notable_exception_raised do
120
+ Rails.logger.debug "BT: #{Card::Error.current.backtrace*"\n "}"
121
+ end
122
+
123
+
119
124
  def event_applies? opts
120
125
  if opts[:on]
121
126
  return false unless Array.wrap( opts[:on] ).member? @action
@@ -27,7 +27,7 @@ event :validate_delete, :before=>:approve, :on=>:delete do
27
27
  end
28
28
 
29
29
  undeletable_all_rules_tags = %w{ default style layout create read update delete }
30
- if junction? and left.codename == 'all' and undeletable_all_rules_tags.member? right.codename
30
+ if junction? and l=left and l.codename == 'all' and undeletable_all_rules_tags.member? right.codename
31
31
  errors.add :delete, "#{name} is an indestructible rule"
32
32
  end
33
33
 
@@ -114,6 +114,7 @@ format :html do
114
114
  select_tag("pointer_select", options_for_select(options, card.item_names.first), :class=>'pointer-select')
115
115
  end
116
116
 
117
+
117
118
  def pointer_option_description option
118
119
  pod_name = card.rule(:options_label) || 'description'
119
120
  dcard = Card[ "#{option.name}+#{pod_name}" ]
@@ -173,6 +174,9 @@ event :standardize_items, :before=>:approve, :on=>:save do
173
174
  end
174
175
  end
175
176
 
177
+ def diff_args
178
+ {:format => :pointer}
179
+ end
176
180
 
177
181
  def item_cards args={}
178
182
  if args[:complete]
@@ -29,6 +29,12 @@ end
29
29
 
30
30
  format :html do
31
31
  view :editor, :mod=>PlainText::HtmlFormat
32
+
33
+ view :content_changes do |args|
34
+ %{
35
+ <pre>#{super(args)}</pre>
36
+ }
37
+ end
32
38
 
33
39
  view :core do |args|
34
40
  js = card.compile_coffee _render_raw
@@ -43,4 +49,8 @@ format do
43
49
  view :core do |args|
44
50
  process_content card.compile_coffee(_render_raw)
45
51
  end
52
+ end
53
+
54
+ def diff_args
55
+ {:format=>:text}
46
56
  end
@@ -25,6 +25,7 @@ def chunk_list #turn off autodetection of uri's
25
25
  :inclusion_and_link
26
26
  end
27
27
 
28
+
28
29
  format :html do
29
30
  view :editor, :mod=>PlainText::HtmlFormat
30
31
 
@@ -33,4 +34,12 @@ format :html do
33
34
  # problems with including other css?
34
35
  process_content ::CodeRay.scan( _render_raw, :css ).div, :size=>:icon
35
36
  end
37
+
38
+ view :content_changes, :mod=>CoffeeScript::HtmlFormat
39
+
40
+
41
+ end
42
+
43
+ def diff_args
44
+ {:format=>:text}
36
45
  end
@@ -23,6 +23,7 @@ end
23
23
  format :html do
24
24
 
25
25
  view :editor, :mod=>PlainText::HtmlFormat
26
+ view :content_changes, :mod=>CoffeeScript::HtmlFormat
26
27
 
27
28
  view :core do |args|
28
29
  highlighted_js = ::CodeRay.scan( _render_raw, :js ).div
@@ -30,3 +31,7 @@ format :html do
30
31
  end
31
32
 
32
33
  end
34
+
35
+ def diff_args
36
+ {:format=>:text}
37
+ end
@@ -3,9 +3,13 @@ include Card::Set::Type::Css
3
3
  format :html do
4
4
  view :core, :mod=>Css::HtmlFormat
5
5
  view :editor, :mod=>PlainText::HtmlFormat
6
+ view :content_changes, :mod=>CoffeeScript::HtmlFormat
6
7
  end
7
8
 
8
-
9
+ def diff_args
10
+ {:format=>:text}
11
+ end
12
+
9
13
  format do
10
14
  view :core do |args|
11
15
  process_content compile_scss(_render_raw)
@@ -15,7 +19,9 @@ format do
15
19
  Sass.compile scss, :style=>style
16
20
  rescue =>e
17
21
  e
18
- end
22
+ end
23
+
24
+
19
25
  end
20
26
 
21
27
 
@@ -248,7 +248,7 @@ format :html do
248
248
  if hide_diff
249
249
  new_name
250
250
  else
251
- Card::Diff::DiffBuilder.new(old_name,new_name).complete
251
+ Card::Diff.complete(old_name,new_name)
252
252
  end
253
253
  else
254
254
  old_name
@@ -260,6 +260,9 @@ format :html do
260
260
  "(#{change})"
261
261
  end
262
262
 
263
+
264
+
265
+
263
266
  view :content_changes do |args|
264
267
  if args[:hide_diff]
265
268
  args[:action].new_values[:content]
@@ -292,3 +295,9 @@ format :html do
292
295
  :class=>'slotter', :remote=>true )
293
296
  end
294
297
  end
298
+
299
+ def diff_args
300
+ {:format=>:text}
301
+ end
302
+
303
+
@@ -14,3 +14,7 @@ end
14
14
  def chunk_list
15
15
  :references
16
16
  end
17
+
18
+ def diff_args
19
+ {:format=>:raw}
20
+ end
@@ -30,7 +30,9 @@ describe Card::Set::All::Base do
30
30
  describe 'array' do
31
31
  it "of search items" do
32
32
  Card.create! :name => "n+a", :type=>"Number", :content=>"10"
33
+ sleep 1
33
34
  Card.create! :name => "n+b", :type=>"Phrase", :content=>"say:\"what\""
35
+ sleep 1
34
36
  Card.create! :name => "n+c", :type=>"Number", :content=>"30"
35
37
  c = Card.new :name => 'nplusarray', :content => "{{n+*children+by create|array}}"
36
38
  expect(c.format._render( :core )).to eq(%{["10", "say:\\"what\\"", "30"]})
@@ -8,6 +8,18 @@ describe Card::Set::All::History do
8
8
  history = render_card :history, :name=>"A"
9
9
  assert_view_select history, 'div[class~="card-frame"]'
10
10
  end
11
+
12
+
13
+ describe '#action_summary' do
14
+ subject do
15
+ first = Card.fetch('First')
16
+ first.format.render_action_summary
17
+ end
18
+ it 'should have a summary' do
19
+ assert_view_select subject, 'del[class="diffdel diff-red"]', :text=>'chicken'
20
+ assert_view_select subject, 'ins[class="diffins diff-green"]', :text=>'chick'
21
+ end
22
+ end
11
23
  end
12
24
 
13
25
 
@@ -3,7 +3,3 @@ format :email_html do
3
3
  view :closed_missing do |args| '' end
4
4
  end
5
5
 
6
-
7
- def clean_html?
8
- false
9
- end
@@ -3,8 +3,12 @@ def clean_html?
3
3
  end
4
4
 
5
5
  def deliver args={}
6
- mail = format.render_mail(args)
7
- mail.deliver
6
+ begin
7
+ mail = format.render_mail(args)
8
+ mail.deliver
9
+ rescue Net::SMTPError => exception
10
+ errors.add :exception, exception.message
11
+ end
8
12
  end
9
13
 
10
14
  def process_email_field field, args
@@ -1,110 +1,210 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  #!/usr/bin/env ruby
3
3
 
4
- # require 'card/diff'
5
- # require 'diff'
6
- #
7
- # describe Card::Diff do
8
- # include Card::Diff
9
- #
10
- # before do
11
- # @builder = Card::Diff::DiffBuilder.new 'old', 'new'
12
- # end
13
- #
14
- # it 'should start of tag' do
15
- # assert @builder.start_of_tag?('<')
16
- # assert(!@builder.start_of_tag?('>'))
17
- # assert(!@builder.start_of_tag?('a'))
18
- # end
19
- #
20
- # it 'should end of tag' do
21
- # assert @builder.end_of_tag?('>')
22
- # assert(!@builder.end_of_tag?('<'))
23
- # assert(!@builder.end_of_tag?('a'))
24
- # end
25
- #
26
- # it 'should whitespace' do
27
- # assert @builder.whitespace?(" ")
28
- # assert @builder.whitespace?("\n")
29
- # assert @builder.whitespace?("\r")
30
- # assert(!@builder.whitespace?("a"))
31
- # end
32
- #
33
- # it 'should convert html to list of words simple' do
34
- # assert_equal(
35
- # ['the', ' ', 'original', ' ', 'text'],
36
- # @builder.convert_html_to_list_of_words('the original text'))
37
- # end
38
- #
39
- # it 'should convert html to list of words should separate endlines' do
40
- # assert_equal(
41
- # ['a', "\n", 'b', "\r", 'c'],
42
- # @builder.convert_html_to_list_of_words("a\nb\rc"))
43
- # end
44
- #
45
- # it 'should convert html to list of words should not compress whitespace' do
46
- # assert_equal(
47
- # ['a', ' ', 'b', ' ', 'c', "\r \n ", 'd'],
48
- # @builder.convert_html_to_list_of_words("a b c\r \n d"))
49
- # end
50
- #
51
- # it 'should convert html to list of words should handle tags well' do
52
- # assert_equal(
53
- # ['<p>', 'foo', ' ', 'bar', '</p>'],
54
- # @builder.convert_html_to_list_of_words("<p>foo bar</p>"))
55
- # end
56
- #
57
- # it 'should convert html to list of words interesting' do
58
- # assert_equal(
59
- # ['<p>', 'this', ' ', 'is', '</p>', "\r\n", '<p>', 'the', ' ', 'new', ' ', 'string',
60
- # '</p>', "\r\n", '<p>', 'around', ' ', 'the', ' ', 'world', '</p>'],
61
- # @builder.convert_html_to_list_of_words(
62
- # "<p>this is</p>\r\n<p>the new string</p>\r\n<p>around the world</p>"))
63
- # end
64
- #
65
- # it 'should html diff simple' do
66
- # a = 'this was the original string'
67
- # b = 'this is the new string'
68
- # assert_equal('this <del class="diffmod">was</del><ins class="diffmod">is</ins> the ' +
69
- # '<del class="diffmod">original</del><ins class="diffmod">new</ins> string',
70
- # diff(a, b))
71
- # end
72
- #
73
- # it 'should html diff with multiple paragraphs' do
74
- # a = "<p>this was the original string</p>"
75
- # b = "<p>this is</p>\r\n<p> the new string</p>\r\n<p>around the world</p>"
76
- #
77
- # # Some of this expected result is accidental to implementation.
78
- # # At least it's well-formed and more or less correct.
79
- # assert_equal(
80
- # "<p>this <del class=\"diffmod\">was</del><ins class=\"diffmod\">is</ins></p>"+
81
- # "<ins class=\"diffmod\">\r\n</ins><p> the " +
82
- # "<del class=\"diffmod\">original</del><ins class=\"diffmod\">new</ins>" +
83
- # " string</p><ins class=\"diffins\">\r\n</ins>" +
84
- # "<p><ins class=\"diffins\">around the world</ins></p>",
85
- # diff(a, b))
86
- # end
87
- #
88
- # # FIXME this test fails (ticket #67, http://dev.instiki.org/ticket/67)
89
- # it 'should html diff preserves endlines in pre' do
90
- # a = "<pre>\na\nb\nc\n</pre>"
91
- # b = "<pre>\n</pre>"
92
- # assert_equal(
93
- # "<pre>\n<del class=\"diffdel\">a\nb\nc\n</del></pre>",
94
- # diff(a, b))
95
- # end
96
- #
97
- # it 'should html diff with tags' do
98
- # a = ""
99
- # b = "<div>foo</div>"
100
- # assert_equal '<div><ins class="diffins">foo</ins></div>', diff(a, b)
101
- # end
102
- #
103
- # it 'should diff for tag change' do
104
- # a = "<a>x</a>"
105
- # b = "<b>x</b>"
106
- # # FIXME sad, but true - this case produces an invalid XML. If handle this you can, strong your foo is.
107
- # assert_equal '<a><b>x</a></b>', diff(a, b)
108
- # end
109
- #
110
- # end
4
+ require 'card/diff'
5
+
6
+ describe Card::Diff do
7
+
8
+ def del text
9
+ "<del class='diffdel diff-red'>#{text}</del>"
10
+ end
11
+ def ins text
12
+ "<ins class='diffins diff-green'>#{text}</ins>"
13
+ end
14
+ def tag text
15
+ "&lt;#{text}&gt;"
16
+ end
17
+ def diff old_s, new_s, opts=@opts
18
+ Card::Diff.complete(old_s, new_s, opts)
19
+ end
20
+
21
+ def summary old_s, new_s, opts=@opts
22
+ Card::Diff.summary(old_s, new_s, opts)
23
+ end
24
+
25
+
26
+ old_p = '<p>old</p>'
27
+ new_p = '<p>new</p>'
28
+ new_h = '<h1>new</h1>'
29
+ def p_diff
30
+ diff '<p>old</p>', '<p>new</p>'
31
+ end
32
+
33
+ describe 'traffic light' do
34
+ it 'is green for addition' do
35
+ a = "a"
36
+ b = "a b"
37
+ db = Card::Diff::DiffBuilder.new(a,b)
38
+ expect(db.green?).to be_truthy
39
+ expect(db.red?).to be_falsey
40
+ end
41
+ it 'is red for deletion' do
42
+ a = "a"
43
+ b = ""
44
+ db = Card::Diff::DiffBuilder.new(a,b)
45
+ expect(db.green?).to be_falsey
46
+ expect(db.red?).to be_truthy
47
+ end
48
+ it 'is green and red for change' do
49
+ a = "a"
50
+ b = "b"
51
+ db = Card::Diff::DiffBuilder.new(a,b)
52
+ expect(db.green?).to be_truthy
53
+ expect(db.red?).to be_truthy
54
+ end
55
+ it 'is off for no change' do
56
+ a = "a"
57
+ b = "a"
58
+ db = Card::Diff::DiffBuilder.new(a,b)
59
+ expect(db.green?).to be_falsey
60
+ expect(db.red?).to be_falsey
61
+ end
62
+ end
63
+
64
+
65
+ describe 'summary' do
66
+ before(:all) do
67
+ @opts = {:format=>:html}
68
+ end
69
+
70
+ it 'omits unchanged text' do
71
+ a = "<p>this was the original string</p>"
72
+ b = "<p>this is the new string</p>"
73
+ expect(summary a, b).to eq(
74
+ "...#{del 'was'}#{ins 'is'}...#{del 'original'}#{ins 'new'}..."
75
+ )
76
+ end
77
+
78
+ it 'no ellipsis if changes fit exactly' do
79
+ a = "123"
80
+ b = "456"
81
+ expect(summary a, b, :summary=>{:length=>6}).to eq(
82
+ "#{del '123'}#{ins '456'}"
83
+ )
84
+ end
85
+
86
+ it 'green ellipsis if added text does not fit' do
87
+ a = "123"
88
+ b = "5678"
89
+ expect(summary a, b, :summary=>{:length=>6}).to eq(
90
+ "#{del '123'}#{ins '...'}"
91
+ )
92
+ end
93
+
94
+ it 'neutral ellipsis if complete change does not fit' do
95
+ a = "123 123"
96
+ b = "456 456"
97
+ expect(summary a, b, :summary=>{:length=>9}).to eq(
98
+ "#{del '123'}#{ins '456'}..."
99
+ )
100
+ end
101
+
102
+ it 'red ellipsis if deleted text partially fits' do
103
+ a = "123456"
104
+ b = "567"
105
+ expect(summary a, b, :summary=>{:length=>4}).to eq(
106
+ "#{del '1...'}"
107
+ )
108
+ end
109
+
110
+ it 'green ellipsis if added text partially fits' do
111
+ a = "1234"
112
+ b = "56789"
113
+ expect(summary a, b, :summary=>{:length=>8}).to eq(
114
+ "#{del '1234'}#{ins '5...'}"
115
+ )
116
+ end
117
+
118
+ it 'removes html tags' do
119
+ a = "<a>A</a>"
120
+ b = "<b>B</b>"
121
+ expect(summary a, b, :format=>:html).to eq(
122
+ "#{del 'A'}#{ins 'B'}"
123
+ )
124
+ end
125
+
126
+ it 'with html tags in raw format' do
127
+ a = "<a>1</a>"
128
+ b = "<b>1</b>"
129
+ expect(summary a, b, :format=>:raw).to eq(
130
+ "#{del( tag 'a' )}#{ins(tag 'b')}...#{del( tag '/a' )}#{ins(tag '/b')}"
131
+ )
132
+ end
133
+
134
+ end
135
+
136
+ context "html format" do
137
+ before(:all) do
138
+ @opts = {:format=>:html}
139
+ end
140
+
141
+ it "doesn't change a text without changes" do
142
+ text = "Hello World!\n How are you?"
143
+ expect(diff text, text).to eq(text)
144
+ end
145
+ it 'preserves html' do
146
+ expect(p_diff).to eq("<p>#{del 'old'}#{ins 'new'}</p>")
147
+ end
148
+ it 'ignores html changes' do
149
+ expect(diff old_p, new_h).to eq("<h1>#{del 'old'}#{ins 'new'}</h1>")
150
+ end
151
+
152
+ it 'diff with multiple paragraphs' do
153
+ a = "<p>this was the original string</p>"
154
+ b = "<p>this is</p>\n<p> the new string</p>\n<p>around the world</p>"
155
+
156
+ expect(diff a, b).to eq(
157
+ "<p>this #{del 'was'}#{ins 'is'}</p>"+
158
+ "\n<p> the " +
159
+ "#{del 'original'}#{ins 'new'}" +
160
+ " string</p>\n" +
161
+ "<p>#{ins 'around the world'}</p>"
162
+ )
163
+ end
164
+ end
165
+
166
+ context "text format" do
167
+ before(:all) do
168
+ @opts = {:format=>:text}
169
+ end
170
+
171
+ it 'removes html' do
172
+ expect(p_diff).to eq("#{del 'old'}#{ins 'new'}")
173
+ end
174
+
175
+ it 'compares complete links' do
176
+ diff = Card::Diff.complete("[[A]]\n[[B]]", "[[A]]\n[[C]]", :format=>:html)
177
+ expect(diff).to eq( "[[A]]\n#{del '[[B]]'}#{ins '[[C]]'}")
178
+ end
179
+
180
+ it 'compares complete inclusions' do
181
+ diff = Card::Diff.complete("{{A}}\n{{B}}", "{{A}}\n{{C}}", :format=>:html)
182
+ expect(diff).to eq( "{{A}}\n#{del '{{B}}'}#{ins '{{C}}'}")
183
+ end
184
+
185
+ end
186
+
187
+ context "raw format" do
188
+ before(:all) do
189
+ @opts = {:format=>:raw}
190
+ end
191
+
192
+ it 'excapes html' do
193
+ expect(p_diff).to eq("#{tag 'p'}#{del 'old'}#{ins 'new'}#{tag '/p'}")
194
+ end
195
+
196
+ it 'diff for tag change' do
197
+ expect(diff old_p, new_h).to eq( del("#{tag 'p'}old#{tag '/p'}") + ins("#{tag 'h1'}new#{tag '/h1'}") )
198
+ end
199
+ end
200
+
201
+ context 'pointer format' do
202
+ before(:all) do
203
+ @opts = {:format=>:pointer}
204
+ end
205
+
206
+ it 'removes square brackets' do
207
+ expect(diff "[[Hello]]", "[[Hi]]").to eq( del('Hello') + ins('Hi') )
208
+ end
209
+ end
210
+ end