diff_matcher 2.4.1 → 2.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 263716b9ab7bbdc763e3ee639f6a8ecdcca95661
4
- data.tar.gz: 193438c3843d95b7dd6d1d311ea7f5da4c98d6e2
2
+ SHA256:
3
+ metadata.gz: ae30490620e0407789851f3b58ecdbf8c0de16b4ec6695b19a77d1809cadfe59
4
+ data.tar.gz: a00b708d6ded4b931c75858c41040e10fc4362d3fbeb55c2f6f63ee8eaf20164
5
5
  SHA512:
6
- metadata.gz: abbfb0e8738b88efc5a8d5546cb02e7ffc845c76255d7cf1542391c8140abdec7b21d072cb9a913d7d75f876b47a21f7e6b2a71e80c99e0f9490ada00f922571
7
- data.tar.gz: f1d2222a64acc05739651604c378a4a9f33998d91af454f3d0c3805fa02bc0b1d7ec81032ec284da8c0c7afef5d845e46eeac81ad40eb60a30a22a842c3a1192
6
+ metadata.gz: 35619bf1f55bdb50a50f69e90483c233236cec6bce7f721dcf8e007533653cadec5b492499d795de648af323d31c4d4142a60daac2386d37641ee41a354c7fa9
7
+ data.tar.gz: 47a9e874d8da2f0d5b623b5077487d1b07138a6d74d04eae2ee32c873f841332cc4ffc26e9cc61c36402176a6636ba2c0b14b56985a24136475261b709b3a9af
@@ -5,8 +5,22 @@ rvm:
5
5
  - 1.9.2
6
6
  - 1.9.3
7
7
  - rbx
8
- # - rbx-19mode
8
+ - rbx-19mode
9
+ - rbx-2
9
10
  - jruby
10
11
  - ree
11
- # - ruby-head
12
12
  - 2.0.0
13
+ - 2.1
14
+ - 2.2
15
+ - 2.3.0
16
+ - ruby-head
17
+
18
+ before_install:
19
+ - gem install bundler -v '1.11.2'
20
+
21
+ matrix:
22
+ fast_finish: true
23
+ allow_failures:
24
+ - rvm: rbx
25
+ - rvm: rbx-19mode
26
+ - rvm: rbx-2
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ### v2.8.0
4
+
5
+ * Add new diff-* executables for matching JSON & CSV files on the command line
6
+
7
+ ### v2.7.1
8
+
9
+ * Use `failure_message` from RSpec matchers in diff output. (denyago)
10
+
11
+ ### v2.7.0
12
+
13
+ * Add rspec custom matcher `be_json_matching` for Rspec v2.x & v3.x
14
+
15
+ ### v2.6.0
16
+
17
+ * Add rspec custom matcher `be_matching` for RSpec v3.x
18
+
19
+ ### v2.5.0
20
+
21
+ * Add rspec custom matcher `be_matching`
22
+
3
23
  ### v2.4.1
4
24
 
5
25
  * BUGFIX match values where their classes are different but one is a subclass of the other
data/README.md CHANGED
@@ -5,21 +5,23 @@ DiffMatcher
5
5
  [![Gem Version](https://badge.fury.io/rb/diff_matcher.png)](http://badge.fury.io/rb/diff_matcher)
6
6
  [![Dependency Status](https://gemnasium.com/diff-matcher/diff_matcher.png)](https://gemnasium.com/diff-matcher/diff_matcher)
7
7
  [![still maintained](http://stillmaintained.com/diff-matcher/diff_matcher.png)](http://stillmaintained.com/diff-matcher/diff_matcher)
8
+ [![diff_matcher API Documentation](https://www.omniref.com/ruby/gems/diff_matcher.png)](https://www.omniref.com/ruby/gems/diff_matcher)
8
9
 
9
10
  Generates a diff by matching against user-defined matchers written in ruby.
10
11
 
11
12
  DiffMatcher matches input data (eg. from a JSON API) against values,
12
- ranges, classes, regexes, procs, custom matchers and/or easily composed,
13
+ ranges, classes, regexes, procs, custom matchers, RSpec matchers and/or easily composed,
13
14
  nested combinations thereof to produce an easy to read diff string.
14
15
 
15
16
  Actual input values are matched against expected matchers in the following way:
16
17
 
17
18
  ``` ruby
18
- actual.is_a? expected # when expected is a class
19
- expected.match actual # when expected is a regexp
20
- expected.call actual # when expected is a proc
21
- actual == expected # when expected is anything else
22
- expected.diff actual # when expected is a built-in DiffMatcher
19
+ actual.is_a? expected # when expected is a class
20
+ expected.match actual # when expected is a regexp
21
+ expected.call actual # when expected is a proc
22
+ expected.matches? actual # when expected implements an RSpec Matcher interface
23
+ actual == expected # when expected is anything else
24
+ expected.diff actual # when expected is a built-in DiffMatcher
23
25
  ```
24
26
 
25
27
  Using these building blocks, more complicated nested matchers can be
@@ -32,7 +34,7 @@ actual = { :a=>{ :a1=>10, :a2=>12 }, :b=>[ 21 ], :c=>'3' , :d=>4 , :e=
32
34
  puts DiffMatcher::difference(expected, actual, :color_scheme=>:white_background)
33
35
  ```
34
36
 
35
- ![example output](https://raw.github.com/playup/diff_matcher/master/doc/diff_matcher.gif)
37
+ ![example output](https://raw.github.com/diff-matcher/diff_matcher/master/doc/diff_matcher.gif)
36
38
 
37
39
 
38
40
  Installation
@@ -200,6 +202,43 @@ puts DiffMatcher::difference(expected, [1, 2.00, "3"])
200
202
  # => Where, - 1 missing, + 1 additional, | 2 match_matcher
201
203
  ```
202
204
 
205
+ When `actual` is matched against some custom logic, an object with an RSpec Matcher
206
+ interface can be used. (NB. `#mathches?(actual)`, `#description` and `#failure_message`
207
+ methods must be implemented.)
208
+
209
+ So you can use one of the RSpec matchers or you can implement your own.
210
+
211
+ ```ruby
212
+ class BeAWeekend
213
+ def matches?(day)
214
+ @day = day
215
+ %w{Sat Sun}.include?(day)
216
+ end
217
+
218
+ def description
219
+ 'be a weekend day'
220
+ end
221
+
222
+ def failure_message
223
+ "expected #{@day} to #{description}"
224
+ end
225
+ end
226
+
227
+ be_a_weekend = BeAWeekend.new
228
+ puts DiffMatcher::difference(be_a_weekend, 'Mon')
229
+ # => - expected Mon to be a weekend day+ "Mon"
230
+ # => Where, - 1 missing, + 1 additional
231
+
232
+
233
+ all_be_weekends = DiffMatcher::AllMatcher.new(be_a_weekend)
234
+ puts DiffMatcher::difference(all_be_weekends, ['Sat', 'Mon'])
235
+ # => [
236
+ # => R "Sat" be a weekend day,
237
+ # => - expected Mon to be a weekend day+ "Mon"
238
+ # => ]
239
+ # => Where, - 1 missing, + 1 additional, R 1 match_rspec
240
+ ```
241
+
203
242
  ### Matcher options
204
243
 
205
244
  Matcher options can be passed to `DiffMatcher::difference` or `DiffMatcher::Matcher#diff`
@@ -284,6 +323,7 @@ in the following way:
284
323
  match matcher => "| "
285
324
  match range => ". "
286
325
  match proc => "{ "
326
+ match rspec => "R "
287
327
 
288
328
 
289
329
  #### Colours
@@ -300,6 +340,7 @@ Using the `:default` colour scheme items shown in a difference are coloured as f
300
340
  match matcher => blue
301
341
  match range => cyan
302
342
  match proc => cyan
343
+ match rspec => cyan
303
344
 
304
345
  Other colour schemes, eg. `:color_scheme=>:white_background` will use different colour mappings.
305
346
 
@@ -355,42 +396,11 @@ do pattern matching and also looks like a good alternative to diff_matcher, it h
355
396
 
356
397
  Use with rspec
357
398
  ---
358
- To use with rspec, create a custom matcher. The following example matcher works with rspec-1.2.4 and up.
399
+ To use with rspec, require it in `spec_helper.rb`
359
400
 
360
401
  ``` ruby
361
- require 'diff_matcher'
362
-
363
- # Uses the diff_matcher gem to provide advanced matching abilities, along with nice visual representation of the
364
- # diff between actual and expected. The functionality set is very helpful for comparing hashes.
365
- #
366
- # Usage examples:
367
- # it { should be_matching(my_var) }
368
- # it { should be_matching(my_var).with_options(ignore_additional: true) }
369
- #
370
- # Options: by default, color_enabled is controlled by Rspec, and quiet is set to true.
371
- RSpec::Matchers.define :be_matching do |expected|
372
- match do |actual|
373
- options = { :color_enabled => RSpec::configuration.color_enabled?, :quiet => true }.merge(@options || {})
374
- @difference = DiffMatcher::Difference.new(expected, actual, options)
375
- @difference.matching?
376
- end
377
-
378
- chain :with_options do |options|
379
- @options = options
380
- end
381
-
382
- failure_message_for_should do |actual|
383
- "diff is:\n" + @difference.to_s
384
- end
385
-
386
- failure_message_for_should_not do |actual|
387
- "diff is:\n" + @difference.to_s
388
- end
389
-
390
- description do
391
- "match via DiffMatcher #{expected}" + (@options.blank? ? '' : " with options: #{@options}")
392
- end
393
- end
402
+ require 'diff_matcher/rspec' # for RSpec version < 3.0
403
+ require 'diff_matcher/rspec_3' # for RSpec version >= 3.x
394
404
  ```
395
405
 
396
406
  And use it with:
@@ -427,6 +437,75 @@ Finished in 0.00601 seconds
427
437
  ```
428
438
 
429
439
 
440
+ Comparing to built-in rspec matcher
441
+ ---
442
+ RSpec 3 now has a built-in complex matcher:
443
+ ``` ruby
444
+ RSpec.describe "a complex example" do
445
+ let(:response) {{person: {first_name: "Noel", last_name: "Rappin"},
446
+ company: {name: "Table XI", url: "www.tablexi.com"}}}
447
+
448
+ it "gets the right response" do
449
+ expect(response).to match({
450
+ person: {first_name: "Avdi", last_name: "Grim"},
451
+ company: {name: "ShipRise", url: a_string_matching(/tablexi/)}
452
+ })
453
+ end
454
+ end
455
+ ```
456
+
457
+ With `--color` set, will result in:
458
+
459
+ ![built-in complex matcher](https://raw.github.com/diff-matcher/diff_matcher/master/doc/builtin_complex_matcher.png)
460
+
461
+
462
+ But using `diff_matcher`:
463
+ ``` ruby
464
+ require "diff_matcher/rspec_3"
465
+
466
+ RSpec.describe "a complex example" do
467
+ let(:response) {{person: {first_name: "Noel", last_name: "Rappin"},
468
+ company: {name: "Table XI", url: "www.tablexi.com"}}}
469
+
470
+ it "gets the right response" do
471
+ expect(response).to be_matching({
472
+ person: {first_name: "Avdi", last_name: "Grim"},
473
+ company: {name: "ShipRise", url: /tablexi/}
474
+ }).with_options(quiet: false)
475
+ end
476
+ end
477
+ ```
478
+
479
+ With `--color` set, will result in:
480
+
481
+ ![diff-matcher](https://raw.github.com/diff-matcher/diff_matcher/master/doc/diff_matcher.png)
482
+
483
+ ie. by making these changes:
484
+ ``` diff
485
+ --- more_tapas_spec.rb 2017-03-02 19:51:26.000000000 +1100
486
+ +++ even_more_tapas_spec.rb 2017-03-02 20:41:52.000000000 +1100
487
+ @@ -1,11 +1,13 @@
488
+ +require "diff_matcher/rspec_3"
489
+ +
490
+ RSpec.describe "a complex example" do
491
+ let(:response) {{person: {first_name: "Noel", last_name: "Rappin"},
492
+ company: {name: "Table XI", url: "www.tablexi.com"}}}
493
+
494
+ it "gets the right response" do
495
+ - expect(response).to match({
496
+ + expect(response).to be_matching({
497
+ person: {first_name: "Avdi", last_name: "Grim"},
498
+ - company: {name: "ShipRise", url: a_string_matching(/tablexi/)}
499
+ - })
500
+ + company: {name: "ShipRise", url: /tablexi/}
501
+ + }).with_options(quiet: false)
502
+ end
503
+ end
504
+ ```
505
+
506
+ NB. Its not as easy to see with RSpec's built-in complex matcher that the url actually matched in the above example.
507
+
508
+
430
509
  Contributing
431
510
  ---
432
511
 
data/TODO.txt CHANGED
@@ -12,3 +12,7 @@ ie. by matching `actual` against an `expected` value/pattern/class/proc.
12
12
  Wed Dec 14 2011
13
13
  - underline
14
14
  - string diff
15
+
16
+
17
+ Sat Nov 14 2020
18
+ - add tests for exe/diff-* executables
@@ -10,6 +10,7 @@ Gem::Specification.new do |s|
10
10
  s.authors = ["locochris"]
11
11
  s.email = "chris@locomote.com.au"
12
12
  s.homepage = "http://github.com/diff-matcher/diff_matcher"
13
+ s.licenses = %w{ BSD MIT }
13
14
 
14
15
  s.summary = %q{Generates a diff by matching against user-defined matchers written in ruby.}
15
16
  s.description = <<EOF
@@ -21,4 +22,6 @@ EOF
21
22
  s.files = `git ls-files`.split("\n")
22
23
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
24
  s.require_paths = ["lib"]
25
+ s.bindir = "exe"
26
+ s.executables = s.files.grep(%r{^#{s.bindir}/}) { |f| File.basename(f) }
24
27
  end
Binary file
@@ -0,0 +1,13 @@
1
+ require "diff_matcher/rspec_3"
2
+
3
+ RSpec.describe "a complex example" do
4
+ let(:response) {{person: {first_name: "Noel", last_name: "Rappin"},
5
+ company: {name: "Table XI", url: "www.tablexi.com"}}}
6
+
7
+ it "gets the right response" do
8
+ expect(response).to be_matching({
9
+ person: {first_name: "Avdi", last_name: "Grim"},
10
+ company: {name: "ShipRise", url: /tablexi/}
11
+ }).with_options(quiet: false)
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ RSpec.describe "a complex example" do
2
+ let(:response) {{person: {first_name: "Noel", last_name: "Rappin"},
3
+ company: {name: "Table XI", url: "www.tablexi.com"}}}
4
+
5
+ it "gets the right response" do
6
+ expect(response).to match({
7
+ person: {first_name: "Avdi", last_name: "Grim"},
8
+ company: {name: "ShipRise", url: a_string_matching(/tablexi/)}
9
+ })
10
+ end
11
+ end
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env ruby
2
+ # Given:
3
+ # --- languages-v1.tsv ---
4
+ # id name author first_appeared stable_release
5
+ # 1 ruby Yukihiro Matsumoto 1995 2.7.1
6
+ # 2 python Guido van Rossum 1991 3.9.0
7
+ # 3 jq Stephen Dolan 2013 1.6
8
+ # --- languages-v1.tsv ---
9
+ #
10
+ # --- languages-v2.tsv ---
11
+ # id name author first_appeared stable_release
12
+ # 1 ruby Yukihiro Matsumoto 1995 2.7.2
13
+ # 2 python Guido van Rossum 1991 3.9.0
14
+ # 3 jq Stephen Dolan 2013 1.6
15
+ # --- languages-v2.tsv ---
16
+ #
17
+ # Examples:
18
+ # > diff-csv languages-v1.tsv languages-v2.tsv
19
+ # {
20
+ # 1=>{
21
+ # "stable_release"=>- "2.7.1"+ "2.7.2"
22
+ # }
23
+ # }
24
+ # Where, - 1 missing, + 1 additional
25
+ #
26
+ # > VERBOSE=1 diff-csv languages-v{1,2}.tsv
27
+ # {
28
+ # 1=>{
29
+ # "name"=>"ruby",
30
+ # "author"=>"Yukihiro Matsumoto",
31
+ # "first_appeared"=>1995,
32
+ # "stable_release"=>- "2.7.1"+ "2.7.2"
33
+ # },
34
+ # 2=>{
35
+ # "name"=>"python",
36
+ # "author"=>"Guido van Rossum",
37
+ # "first_appeared"=>1991,
38
+ # "stable_release"=>"3.9.0"
39
+ # },
40
+ # 3=>{
41
+ # "name"=>"jq",
42
+ # "author"=>"Stephen Dolan",
43
+ # "first_appeared"=>2013,
44
+ # "stable_release"=>1.6
45
+ # }
46
+ # }
47
+ # Where, - 1 missing, + 1 additional
48
+ #
49
+ # > KEY=name diff-csv languages-v{1,2}.tsv
50
+ # {
51
+ # "ruby"=>{
52
+ # "stable_release"=>- "2.7.1"+ "2.7.2"
53
+ # }
54
+ # }
55
+ # Where, - 1 missing, + 1 additional
56
+
57
+ require 'csv'
58
+ require 'diff_matcher'
59
+
60
+ COL_SEP=ENV.fetch("COL_SEP", "\t")
61
+ KEY=ENV.fetch("KEY", "id")
62
+
63
+
64
+ def fix_nulls(h)
65
+ h.each { |k, v| h[k] = (v == 'NULL' ? nil : v) }
66
+ end
67
+
68
+ def records(file, key=KEY, col_sep=COL_SEP)
69
+ CSV(file, col_sep: COL_SEP, headers: true, converters: :all).inject({}) do |h, row|
70
+ data = fix_nulls(row.to_hash)
71
+ h.update(data.delete(key)=> data)
72
+ end
73
+ end
74
+
75
+ data0 = records(File.open(ARGV[0]))
76
+ data1 = records(File.open(ARGV[1]))
77
+
78
+ diff_opts = {
79
+ color_enabled: true,
80
+ ignore_additional: ENV['IGNORE_ADDITIONAL'],
81
+ quiet: !ENV['VERBOSE']
82
+ }
83
+
84
+ diff=DiffMatcher.difference(data0, data1, diff_opts)
85
+
86
+ if diff
87
+ puts diff
88
+ exit 1
89
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ require 'diff_matcher'
3
+ require 'json'
4
+
5
+ expected, actual = ARGV.first(2).map do |f|
6
+ JSON.parse(File.read(f))
7
+ end
8
+
9
+ diff=DiffMatcher.difference(expected, actual, color_scheme: :default)
10
+
11
+ if diff
12
+ puts diff
13
+ exit 1
14
+ end
@@ -0,0 +1,93 @@
1
+ #!/bin/bash -e
2
+ # Examples:
3
+ # # Show diff between the TABLES in two databases
4
+ # TABLES="languages" diff-mysql database1 database2
5
+ #
6
+ # # Show diff between languages TABLES skipping any output containing 'python'
7
+ # FILTER_CMD='grep -v python' TABLES=languages diff-mysql database{1,2}
8
+ #
9
+ # # Filter at the database level instead
10
+ # FILTER_SQL="WHERE languages.name = 'python'" TABLES=languages diff-mysql database{1,2}
11
+ #
12
+ set -eo pipefail
13
+
14
+ DB_USERNAME=${DB_USERNAME:-root}
15
+ DB_PASSWORD=${DB_PASSWORD:-password}
16
+ DB_HOST=${DB_HOST:-localhost}
17
+
18
+ MAX_ROW_COUNT=${MAX_ROW_COUNT:-100}
19
+ SKIP=${SKIP:-messages}
20
+
21
+ DB_NAME1=$1
22
+ DB_NAME2=$2
23
+
24
+ puts() { local color=$1; local prefix=$2; local msg=$3
25
+ echo -e "[$(date +%Y%m%d%H%M%S)] [${color};1m${prefix}:[${color}m $msg" 1>&2
26
+ }
27
+
28
+ info() { local msg=$*; puts 34 INFO "$msg" ; }
29
+ success() { local msg=$*; puts 32 SUCCESS "$msg"; }
30
+ error() { local msg=$*; puts 31 ERROR "$msg" ; }
31
+
32
+ skip() { local name=$1
33
+ for skip_name in $SKIP; do
34
+ [ "$skip_name" == "$name" ] && return 0
35
+ done
36
+ return 1
37
+ }
38
+
39
+ do_mysql() { local db_name="$1"; shift
40
+ mysql "$@" --user="$DB_USERNAME" --password="$DB_PASSWORD" --host="$DB_HOST" "$db_name" 2> /dev/null
41
+ }
42
+
43
+ do_mysql_silent() { local db_name=$1
44
+ do_mysql "$db_name" --silent
45
+ }
46
+
47
+ tables() { local db_name=$1
48
+ info "Fetching table names from database $db_name (host '$DB_HOST') ..."
49
+ echo "show tables" |
50
+ do_mysql_silent "$db_name"
51
+ }
52
+ TABLES=${TABLES:-$(tables "$DB_NAME1")}
53
+
54
+ count_rows() { local table=$1; local db_name=$2
55
+ echo "select count(id) from $table" |
56
+ do_mysql_silent "$db_name"
57
+ }
58
+
59
+ diff_cmd() {
60
+ #diff -u $@
61
+ COLOR_ENABLED=1 ${DIFF_CMD:-diff-csv} "$@"
62
+ }
63
+
64
+ filter_cmd() {
65
+ ${FILTER_CMD:-cat}
66
+ }
67
+
68
+ dump_table() { local table=$1; local db_name=$2
69
+ echo "$(echo 'SELECT *') FROM $table ${FILTER_SQL}" |
70
+ do_mysql "$db_name" |
71
+ filter_cmd
72
+ }
73
+
74
+ table_diff() { local table="$1"
75
+ info "Diffing $table ($DB_NAME1 vs $DB_NAME2)"
76
+ diff_cmd <(dump_table "$table" {"$DB_NAME1","$DB_NAME2"})
77
+ }
78
+
79
+
80
+ exit_code=0
81
+ for table in $TABLES; do
82
+ row_count=$(count_rows "$table" "$DB_NAME1")
83
+ if [ $row_count -lt $MAX_ROW_COUNT ]; then
84
+ if skip "$table"; then
85
+ info "Skipping $table (as it was referenced in SKIP)"
86
+ else
87
+ table_diff "$table" || exit_code=$?
88
+ fi
89
+ else
90
+ info "Skipping $table (as row count exceeds MAX_ROW_COUNT, $row_count > $MAX_ROW_COUNT)"
91
+ fi
92
+ done
93
+ exit $exit_code
@@ -88,7 +88,8 @@ module DiffMatcher
88
88
  :match_class => [BLUE , ":"],
89
89
  :match_matcher => [BLUE , "|"],
90
90
  :match_range => [CYAN , "."],
91
- :match_proc => [CYAN , "{"]
91
+ :match_proc => [CYAN , "{"],
92
+ :match_rspec => [CYAN , "R"]
92
93
  }
93
94
 
94
95
  class << self
@@ -186,7 +187,7 @@ module DiffMatcher
186
187
  @matches_shown ||= lambda {
187
188
  ret = []
188
189
  unless @quiet
189
- ret += [:match_matcher, :match_class, :match_range, :match_proc, :match_regexp]
190
+ ret += [:match_matcher, :match_class, :match_range, :match_proc, :match_regexp, :match_rspec]
190
191
  ret += [:match_value]
191
192
  end
192
193
  ret
@@ -273,7 +274,12 @@ module DiffMatcher
273
274
  when Range ; [expected.include?(actual) , :match_range ]
274
275
  when Proc ; [expected.call(actual) , :match_proc ]
275
276
  when Regexp ; [actual.is_a?(String) && actual.match(expected) , :match_regexp ]
276
- else [actual == expected , :match_value ]
277
+ else
278
+ if expected.respond_to?(:matches?)
279
+ [expected.matches?(actual), :match_rspec]
280
+ else
281
+ [actual == expected, :match_value]
282
+ end
277
283
  end
278
284
  end
279
285
 
@@ -294,6 +300,7 @@ module DiffMatcher
294
300
 
295
301
  def match_to_s(expected, actual, match_type)
296
302
  actual = match_regexp_to_s(expected, actual) if match_type == :match_regexp
303
+ actual = "#{actual} #{expected.description}" if match_type == :match_rspec
297
304
  markup(match_type, actual) if matches_shown.include?(match_type)
298
305
  end
299
306
 
@@ -308,6 +315,16 @@ module DiffMatcher
308
315
  end
309
316
  end
310
317
 
318
+ def summarize_rspec_matcher(matcher)
319
+ if matcher.respond_to?(:failure_message)
320
+ matcher.failure_message
321
+ elsif matcher.respond_to?(:failure_message_for_should)
322
+ matcher.failure_message_for_should
323
+ else
324
+ summarize_item(matcher)
325
+ end
326
+ end
327
+
311
328
  def difference_to_s(expected, actual)
312
329
  match, match_type, d = match?(expected, actual)
313
330
  if match
@@ -316,6 +333,8 @@ module DiffMatcher
316
333
  case match_type
317
334
  when :match_matcher
318
335
  d
336
+ when :match_rspec
337
+ "#{markup(:missing, summarize_rspec_matcher(expected))}#{markup(:additional, summarize_item(actual))}"
319
338
  else
320
339
  exp, act = if [expected, actual].any? { |item| item.is_a?(Proc) }
321
340
  [expected, actual].map { |item| item.inspect }
@@ -0,0 +1,3 @@
1
+ require 'rspec/core'
2
+ require 'diff_matcher'
3
+ require 'diff_matcher/rspec/matchers'
@@ -0,0 +1,3 @@
1
+ require 'diff_matcher/rspec/matchers/diff_matcher'
2
+ require 'diff_matcher/rspec/matchers/diff_json_matcher'
3
+
@@ -0,0 +1,31 @@
1
+ # Uses the diff_matcher gem to provide advanced matching abilities, along with nice visual representation of the
2
+ # diff between JSON.parse(actual) and expected. The functionality set is very helpful for comparing hashes.
3
+ #
4
+ # Usage examples:
5
+ # it { should be_matching(my_var) }
6
+ # it { should be_matching(my_var).with_options(ignore_additional: true) }
7
+ #
8
+ # Options: by default, color_enabled is controlled by Rspec, and quiet is set to true.
9
+ RSpec::Matchers.define :be_json_matching do |expected|
10
+ match do |actual|
11
+ options = { :color_enabled => RSpec::configuration.color_enabled?, :quiet => true }.merge(@options || {})
12
+ @difference = DiffMatcher::Difference.new(expected, JSON.parse(actual), options)
13
+ @difference.matching?
14
+ end
15
+
16
+ chain :with_options do |options|
17
+ @options = options
18
+ end
19
+
20
+ failure_message_for_should do |actual|
21
+ "diff is:\n" + @difference.to_s
22
+ end
23
+
24
+ failure_message_for_should_not do |actual|
25
+ "diff is:\n" + @difference.to_s
26
+ end
27
+
28
+ description do
29
+ "match via DiffMatcher #{expected}" + (@options.blank? ? '' : " with options: #{@options}")
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ # Uses the diff_matcher gem to provide advanced matching abilities, along with nice visual representation of the
2
+ # diff between JSON.parse(actual) and expected. The functionality set is very helpful for comparing hashes.
3
+ #
4
+ # Usage examples:
5
+ # it { should be_matching(my_var) }
6
+ # it { should be_matching(my_var).with_options(ignore_additional: true) }
7
+ #
8
+ # Options: by default, color_enabled is controlled by Rspec, and quiet is set to true.
9
+ RSpec::Matchers.define :be_json_matching do |expected|
10
+ match do |actual|
11
+ options = { :color_enabled => RSpec::configuration.color_enabled?, :quiet => true }.merge(@options || {})
12
+ @difference = DiffMatcher::Difference.new(expected, JSON.parse(actual), options)
13
+ @difference.matching?
14
+ end
15
+
16
+ chain :with_options do |options|
17
+ @options = options
18
+ end
19
+
20
+ failure_message_for_should do |actual|
21
+ "diff is:\n" + @difference.to_s
22
+ end
23
+
24
+ failure_message_for_should_not do |actual|
25
+ "diff is:\n" + @difference.to_s
26
+ end
27
+
28
+ description do
29
+ "match via DiffMatcher #{expected}" + (@options.blank? ? '' : " with options: #{@options}")
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ require 'rspec/core'
2
+ require 'diff_matcher'
3
+ require 'diff_matcher/rspec_3/matchers'
@@ -0,0 +1,2 @@
1
+ require 'diff_matcher/rspec_3/matchers/diff_matcher'
2
+ require 'diff_matcher/rspec_3/matchers/diff_json_matcher'
@@ -0,0 +1,31 @@
1
+ # Uses the diff_matcher gem to provide advanced matching abilities, along with nice visual representation of the
2
+ # diff between JSON.parse(actual) and expected. The functionality set is very helpful for comparing hashes.
3
+ #
4
+ # Usage examples:
5
+ # it { should be_matching(my_var) }
6
+ # it { should be_matching(my_var).with_options(ignore_additional: true) }
7
+ #
8
+ # Options: by default, color_enabled is controlled by Rspec, and quiet is set to true.
9
+ RSpec::Matchers.define :be_json_matching do |expected|
10
+ match do |actual|
11
+ options = { :color_enabled => RSpec::configuration.color_enabled?, :quiet => true }.merge(@options || {})
12
+ @difference = DiffMatcher::Difference.new(expected, JSON.parse(actual), options)
13
+ @difference.matching?
14
+ end
15
+
16
+ chain :with_options do |options|
17
+ @options = options
18
+ end
19
+
20
+ failure_message do |actual|
21
+ "diff is:\n" + @difference.to_s
22
+ end
23
+
24
+ failure_message_when_negated do |actual|
25
+ "diff is:\n" + @difference.to_s
26
+ end
27
+
28
+ description do
29
+ "match via DiffMatcher #{expected}" + (@options.blank? ? '' : " with options: #{@options}")
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ # Uses the diff_matcher gem to provide advanced matching abilities, along with nice visual representation of the
2
+ # diff between actual and expected. The functionality set is very helpful for comparing hashes.
3
+ #
4
+ # Usage examples:
5
+ # it { should be_matching(my_var) }
6
+ # it { should be_matching(my_var).with_options(ignore_additional: true) }
7
+ #
8
+ # Options: by default, color_enabled is controlled by Rspec, and quiet is set to true.
9
+ RSpec::Matchers.define :be_matching do |expected|
10
+ match do |actual|
11
+ options = { :color_enabled => RSpec::configuration.color_enabled?, :quiet => true }.merge(@options || {})
12
+ @difference = DiffMatcher::Difference.new(expected, actual, options)
13
+ @difference.matching?
14
+ end
15
+
16
+ chain :with_options do |options|
17
+ @options = options
18
+ end
19
+
20
+ failure_message do |actual|
21
+ "diff is:\n" + @difference.to_s
22
+ end
23
+
24
+ failure_message_when_negated do |actual|
25
+ "diff is:\n" + @difference.to_s
26
+ end
27
+
28
+ description do
29
+ "match via DiffMatcher #{expected}" + (@options.blank? ? '' : " with options: #{@options}")
30
+ end
31
+ end
@@ -1,3 +1,3 @@
1
1
  module DiffMatcher
2
- VERSION = "2.4.1"
2
+ VERSION = "2.8.0"
3
3
  end
@@ -470,6 +470,36 @@ describe "DiffMatcher::difference(expected, actual, opts)" do
470
470
  end
471
471
  end
472
472
 
473
+ context 'a duck-type responding to #matches?' do
474
+ matchable = Class.new do
475
+ def initialize(expected)
476
+ @expected = expected
477
+ end
478
+
479
+ def matches?(actual)
480
+ actual == @expected
481
+ end
482
+
483
+ def failure_message
484
+ "the matcher should be eq '#{@expected}'"
485
+ end
486
+
487
+ def description
488
+ "be eq #{@expected}"
489
+ end
490
+ end
491
+ expected, same, different =
492
+ matchable.new('foo'),
493
+ 'foo',
494
+ 'bar'
495
+
496
+ it_behaves_like "a diff matcher", expected, same, different,
497
+ <<-EOF
498
+ - the matcher should be eq 'foo'+ "bar"
499
+ Where, - 1 missing, + 1 additional
500
+ EOF
501
+ end
502
+
473
503
  context "a proc," do
474
504
  expected, same, different =
475
505
  lambda { |x| [FalseClass, TrueClass].include? x.class },
@@ -654,12 +684,25 @@ describe "DiffMatcher::difference(expected, actual, opts)" do
654
684
  end
655
685
 
656
686
  context "when expected has multiple items," do
687
+ matchable = Class.new do
688
+ def initialize(expected)
689
+ @expected = expected
690
+ end
691
+
692
+ def matches?(actual)
693
+ actual == @expected
694
+ end
695
+
696
+ def description
697
+ "be == #{@expected}"
698
+ end
699
+ end
657
700
  expected, same, different =
658
- [ 1, 2, /\d/, Fixnum, 4..6 , lambda { |x| x % 6 == 0 } ],
659
- [ 1, 2, "3" , 4 , 5 , 6 ],
660
- [ 0, 2, "3" , 4 , 5 , 6 ]
701
+ [ 1, 2, /\d/, Fixnum, 4..6 , lambda { |x| x % 6 == 0 }, matchable.new(7)],
702
+ [ 1, 2, "3" , 4 , 5 , 6 , 7 ],
703
+ [ 0, 2, "3" , 4 , 5 , 6 , 7 ]
661
704
 
662
- describe "it shows regex, class, range, proc matches and matches" do
705
+ describe "it shows regex, class, range, proc matches, matches and RSpec matcher" do
663
706
  it_behaves_like "a diff matcher", expected, same, different,
664
707
  <<-EOF
665
708
  [
@@ -668,9 +711,10 @@ describe "DiffMatcher::difference(expected, actual, opts)" do
668
711
  ~ "(3)",
669
712
  : 4,
670
713
  . 5,
671
- { 6
714
+ { 6,
715
+ R 7 be == 7
672
716
  ]
673
- Where, - 1 missing, + 1 additional, ~ 1 match_regexp, : 1 match_class, . 1 match_range, { 1 match_proc
717
+ Where, - 1 missing, + 1 additional, ~ 1 match_regexp, : 1 match_class, . 1 match_range, { 1 match_proc, R 1 match_rspec
674
718
  EOF
675
719
  end
676
720
 
@@ -693,9 +737,10 @@ describe "DiffMatcher::difference(expected, actual, opts)" do
693
737
  ~ "(3)",
694
738
  : 4,
695
739
  . 5,
696
- { 6
740
+ { 6,
741
+ R 7 be == 7
697
742
  ]
698
- Where, - 1 missing, + 1 additional, ~ 1 match_regexp, : 1 match_class, . 1 match_range, { 1 match_proc
743
+ Where, - 1 missing, + 1 additional, ~ 1 match_regexp, : 1 match_class, . 1 match_range, { 1 match_proc, R 1 match_rspec
699
744
  EOF
700
745
  end
701
746
 
@@ -708,9 +753,10 @@ describe "DiffMatcher::difference(expected, actual, opts)" do
708
753
  \e[0m \e[32m~ \e[0m"\e[32m(\e[1m3\e[0m\e[32m)\e[0m"\e[0m,
709
754
  \e[0m \e[34m: \e[1m4\e[0m,
710
755
  \e[0m \e[36m. \e[1m5\e[0m,
711
- \e[0m \e[36m{ \e[1m6\e[0m
756
+ \e[0m \e[36m{ \e[1m6\e[0m,
757
+ \e[0m \e[36mR \e[1m7 be == 7\e[0m
712
758
  \e[0m]
713
- Where, \e[31m- \e[1m1 missing\e[0m, \e[33m+ \e[1m1 additional\e[0m, \e[32m~ \e[1m1 match_regexp\e[0m, \e[34m: \e[1m1 match_class\e[0m, \e[36m. \e[1m1 match_range\e[0m, \e[36m{ \e[1m1 match_proc\e[0m
759
+ Where, \e[31m- \e[1m1 missing\e[0m, \e[33m+ \e[1m1 additional\e[0m, \e[32m~ \e[1m1 match_regexp\e[0m, \e[34m: \e[1m1 match_class\e[0m, \e[36m. \e[1m1 match_range\e[0m, \e[36m{ \e[1m1 match_proc\e[0m, \e[36mR \e[1m1 match_rspec\e[0m
714
760
  EOF
715
761
 
716
762
  context "on a white background" do
@@ -722,9 +768,10 @@ describe "DiffMatcher::difference(expected, actual, opts)" do
722
768
  \e[0m \e[32m~ \e[0m"\e[32m(\e[1m3\e[0m\e[32m)\e[0m"\e[0m,
723
769
  \e[0m \e[34m: \e[1m4\e[0m,
724
770
  \e[0m \e[36m. \e[1m5\e[0m,
725
- \e[0m \e[36m{ \e[1m6\e[0m
771
+ \e[0m \e[36m{ \e[1m6\e[0m,
772
+ \e[0m \e[36mR \e[1m7 be == 7\e[0m
726
773
  \e[0m]
727
- Where, \e[31m- \e[1m1 missing\e[0m, \e[35m+ \e[1m1 additional\e[0m, \e[32m~ \e[1m1 match_regexp\e[0m, \e[34m: \e[1m1 match_class\e[0m, \e[36m. \e[1m1 match_range\e[0m, \e[36m{ \e[1m1 match_proc\e[0m
774
+ Where, \e[31m- \e[1m1 missing\e[0m, \e[35m+ \e[1m1 additional\e[0m, \e[32m~ \e[1m1 match_regexp\e[0m, \e[34m: \e[1m1 match_class\e[0m, \e[36m. \e[1m1 match_range\e[0m, \e[36m{ \e[1m1 match_proc\e[0m, \e[36mR \e[1m1 match_rspec\e[0m
728
775
  EOF
729
776
  end
730
777
 
@@ -739,9 +786,10 @@ describe "DiffMatcher::difference(expected, actual, opts)" do
739
786
  \e[0m \e[32m~ \e[0m"\e[32m(\e[1m3\e[0m\e[32m)\e[0m"\e[0m,
740
787
  \e[0m \e[34m: \e[1m4\e[0m,
741
788
  \e[0m \e[36m. \e[1m5\e[0m,
742
- \e[0m \e[36m{ \e[1m6\e[0m
789
+ \e[0m \e[36m{ \e[1m6\e[0m,
790
+ \e[0m \e[36mR \e[1m7 be == 7\e[0m
743
791
  \e[0m]
744
- Where, \e[31m- \e[1m1 missing\e[0m, \e[33m+ \e[1m1 additional\e[0m, \e[32m~ \e[1m1 match_regexp\e[0m, \e[34m: \e[1m1 match_class\e[0m, \e[36m. \e[1m1 match_range\e[0m, \e[36m{ \e[1m1 match_proc\e[0m
792
+ Where, \e[31m- \e[1m1 missing\e[0m, \e[33m+ \e[1m1 additional\e[0m, \e[32m~ \e[1m1 match_regexp\e[0m, \e[34m: \e[1m1 match_class\e[0m, \e[36m. \e[1m1 match_range\e[0m, \e[36m{ \e[1m1 match_proc\e[0m, \e[36mR \e[1m1 match_rspec\e[0m
745
793
  EOF
746
794
  end
747
795
 
@@ -756,9 +804,10 @@ describe "DiffMatcher::difference(expected, actual, opts)" do
756
804
  \e[0m \e[32m~ \e[0m"\e[32m(\e[1m3\e[0m\e[32m)\e[0m"\e[0m,
757
805
  \e[0m \e[34m: \e[1m4\e[0m,
758
806
  \e[0m \e[36m. \e[1m5\e[0m,
759
- \e[0m \e[36m{ \e[1m6\e[0m
807
+ \e[0m \e[36m{ \e[1m6\e[0m,
808
+ \e[0m \e[36mR \e[1m7 be == 7\e[0m
760
809
  \e[0m]
761
- Where, \e[31m- \e[1m1 missing\e[0m, \e[35m+ \e[1m1 additional\e[0m, \e[32m~ \e[1m1 match_regexp\e[0m, \e[34m: \e[1m1 match_class\e[0m, \e[36m. \e[1m1 match_range\e[0m, \e[36m{ \e[1m1 match_proc\e[0m
810
+ Where, \e[31m- \e[1m1 missing\e[0m, \e[35m+ \e[1m1 additional\e[0m, \e[32m~ \e[1m1 match_regexp\e[0m, \e[34m: \e[1m1 match_class\e[0m, \e[36m. \e[1m1 match_range\e[0m, \e[36m{ \e[1m1 match_proc\e[0m, \e[36mR \e[1m1 match_rspec\e[0m
762
811
  EOF
763
812
  end
764
813
  end
@@ -778,9 +827,10 @@ describe "DiffMatcher::difference(expected, actual, opts)" do
778
827
  \e[0m \e[32m~ \e[0m"\e[32m(\e[1m3\e[0m\e[32m)\e[0m"\e[0m,
779
828
  \e[0m \e[34m: \e[1m4\e[0m,
780
829
  \e[0m \e[36m. \e[1m5\e[0m,
781
- \e[0m \e[36m{ \e[1m6\e[0m
830
+ \e[0m \e[36m{ \e[1m6\e[0m,
831
+ \e[0m \e[36mR \e[1m7 be == 7\e[0m
782
832
  \e[0m]
783
- Where, \e[31m- \e[1m1 missing\e[0m, \e[35m+ \e[1m1 additional\e[0m, \e[32m~ \e[1m1 match_regexp\e[0m, \e[34m: \e[1m1 match_class\e[0m, \e[36m. \e[1m1 match_range\e[0m, \e[36m{ \e[1m1 match_proc\e[0m
833
+ Where, \e[31m- \e[1m1 missing\e[0m, \e[35m+ \e[1m1 additional\e[0m, \e[32m~ \e[1m1 match_regexp\e[0m, \e[34m: \e[1m1 match_class\e[0m, \e[36m. \e[1m1 match_range\e[0m, \e[36m{ \e[1m1 match_proc\e[0m, \e[36mR \e[1m1 match_rspec\e[0m
784
834
  EOF
785
835
  end
786
836
 
@@ -794,9 +844,10 @@ describe "DiffMatcher::difference(expected, actual, opts)" do
794
844
  <span style=\"color:green\">~ </b></span>\"<span style=\"color:green\">(<b>3</b></span><span style=\"color:green\">)</b></span>\"</b></span>,
795
845
  <span style=\"color:blue\">: <b>4</b></span>,
796
846
  <span style=\"color:cyan\">. <b>5</b></span>,
797
- <span style=\"color:cyan\">{ <b>6</b></span>
847
+ <span style=\"color:cyan\">{ <b>6</b></span>,
848
+ <span style=\"color:cyan\">R <b>7 be == 7</b></span>
798
849
  ]
799
- Where, <span style=\"color:red\">- <b>1 missing</b></span>, <span style=\"color:magenta\">+ <b>1 additional</b></span>, <span style=\"color:green\">~ <b>1 match_regexp</b></span>, <span style=\"color:blue\">: <b>1 match_class</b></span>, <span style=\"color:cyan\">. <b>1 match_range</b></span>, <span style=\"color:cyan\">{ <b>1 match_proc</b></span>
850
+ Where, <span style=\"color:red\">- <b>1 missing</b></span>, <span style=\"color:magenta\">+ <b>1 additional</b></span>, <span style=\"color:green\">~ <b>1 match_regexp</b></span>, <span style=\"color:blue\">: <b>1 match_class</b></span>, <span style=\"color:cyan\">. <b>1 match_range</b></span>, <span style=\"color:cyan\">{ <b>1 match_proc</b></span>, <span style=\"color:cyan\">R <b>1 match_rspec</b></span>
800
851
  </pre>
801
852
  EOF
802
853
  end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+ require 'diff_matcher/rspec'
3
+
4
+ describe :be_matching do
5
+ it "should call DiffMatcher::Difference" do
6
+ pending 'how are custom matchers tested now?'
7
+ DiffMatcher::Difference.should_receive(:new).with(
8
+ :expected, :actual, { :color_enabled => RSpec::configuration.color_enabled?, :quiet => true }.merge({ :foo => 'bar' })
9
+ ).and_return(double(:matching? => true))
10
+
11
+ :actual.should be_matching(:expected).with_options :foo => 'bar'
12
+ end
13
+ end
metadata CHANGED
@@ -1,44 +1,64 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: diff_matcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.1
4
+ version: 2.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - locochris
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2013-07-28 00:00:00.000000000 Z
11
+ date: 2020-11-14 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
14
  DiffMatcher matches input data (eg. from a JSON API) against values,
15
15
  ranges, classes, regexes, procs, custom matchers and/or easily composed,
16
16
  nested combinations thereof to produce an easy to read diff string.
17
17
  email: chris@locomote.com.au
18
- executables: []
18
+ executables:
19
+ - diff-csv
20
+ - diff-json
21
+ - diff-mysql
19
22
  extensions: []
20
23
  extra_rdoc_files: []
21
24
  files:
22
- - .gitignore
23
- - .rspec
24
- - .travis.yml
25
+ - ".gitignore"
26
+ - ".rspec"
27
+ - ".travis.yml"
25
28
  - CHANGELOG.md
26
29
  - Gemfile
27
- - License.txt
28
30
  - README.md
29
31
  - Rakefile
30
32
  - TODO.txt
31
33
  - diff_matcher.gemspec
34
+ - doc/builtin_complex_matcher.png
32
35
  - doc/diff_matcher.gif
36
+ - doc/diff_matcher.png
37
+ - doc/even_more_tapas_spec.rb
33
38
  - doc/example_output.png
39
+ - doc/more_tapas_spec.rb
40
+ - exe/diff-csv
41
+ - exe/diff-json
42
+ - exe/diff-mysql
34
43
  - lib/diff_matcher.rb
35
44
  - lib/diff_matcher/difference.rb
36
45
  - lib/diff_matcher/escape_to_html.rb
46
+ - lib/diff_matcher/rspec.rb
47
+ - lib/diff_matcher/rspec/matchers.rb
48
+ - lib/diff_matcher/rspec/matchers/diff_json_matcher.rb
49
+ - lib/diff_matcher/rspec/matchers/diff_matcher.rb
50
+ - lib/diff_matcher/rspec_3.rb
51
+ - lib/diff_matcher/rspec_3/matchers.rb
52
+ - lib/diff_matcher/rspec_3/matchers/diff_json_matcher.rb
53
+ - lib/diff_matcher/rspec_3/matchers/diff_matcher.rb
37
54
  - lib/diff_matcher/version.rb
38
55
  - spec/diff_matcher/difference_spec.rb
56
+ - spec/diff_matcher/rspec/matchers/diff_matcher_spec.rb
39
57
  - spec/spec_helper.rb
40
58
  homepage: http://github.com/diff-matcher/diff_matcher
41
- licenses: []
59
+ licenses:
60
+ - BSD
61
+ - MIT
42
62
  metadata: {}
43
63
  post_install_message:
44
64
  rdoc_options: []
@@ -46,20 +66,21 @@ require_paths:
46
66
  - lib
47
67
  required_ruby_version: !ruby/object:Gem::Requirement
48
68
  requirements:
49
- - - '>='
69
+ - - ">="
50
70
  - !ruby/object:Gem::Version
51
71
  version: '0'
52
72
  required_rubygems_version: !ruby/object:Gem::Requirement
53
73
  requirements:
54
- - - '>='
74
+ - - ">="
55
75
  - !ruby/object:Gem::Version
56
76
  version: '0'
57
77
  requirements: []
58
78
  rubyforge_project:
59
- rubygems_version: 2.0.3
79
+ rubygems_version: 2.7.6
60
80
  signing_key:
61
81
  specification_version: 4
62
82
  summary: Generates a diff by matching against user-defined matchers written in ruby.
63
83
  test_files:
64
84
  - spec/diff_matcher/difference_spec.rb
85
+ - spec/diff_matcher/rspec/matchers/diff_matcher_spec.rb
65
86
  - spec/spec_helper.rb
@@ -1,22 +0,0 @@
1
- (The MIT License)
2
-
3
- Copyright (c) 2011 PlayUp
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.