diff_matcher 2.7.1 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +4 -0
- data/README.md +70 -1
- data/TODO.txt +4 -0
- data/diff_matcher.gemspec +2 -0
- data/doc/builtin_complex_matcher.png +0 -0
- data/doc/diff_matcher.png +0 -0
- data/doc/even_more_tapas_spec.rb +13 -0
- data/doc/more_tapas_spec.rb +11 -0
- data/exe/diff-csv +89 -0
- data/exe/diff-json +14 -0
- data/exe/diff-mysql +93 -0
- data/lib/diff_matcher/version.rb +1 -1
- metadata +15 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ae30490620e0407789851f3b58ecdbf8c0de16b4ec6695b19a77d1809cadfe59
|
4
|
+
data.tar.gz: a00b708d6ded4b931c75858c41040e10fc4362d3fbeb55c2f6f63ee8eaf20164
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35619bf1f55bdb50a50f69e90483c233236cec6bce7f721dcf8e007533653cadec5b492499d795de648af323d31c4d4142a60daac2386d37641ee41a354c7fa9
|
7
|
+
data.tar.gz: 47a9e874d8da2f0d5b623b5077487d1b07138a6d74d04eae2ee32c873f841332cc4ffc26e9cc61c36402176a6636ba2c0b14b56985a24136475261b709b3a9af
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -34,7 +34,7 @@ actual = { :a=>{ :a1=>10, :a2=>12 }, :b=>[ 21 ], :c=>'3' , :d=>4 , :e=
|
|
34
34
|
puts DiffMatcher::difference(expected, actual, :color_scheme=>:white_background)
|
35
35
|
```
|
36
36
|
|
37
|
-

|
38
38
|
|
39
39
|
|
40
40
|
Installation
|
@@ -437,6 +437,75 @@ Finished in 0.00601 seconds
|
|
437
437
|
```
|
438
438
|
|
439
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
|
+

|
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
|
+

|
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
|
+
|
440
509
|
Contributing
|
441
510
|
---
|
442
511
|
|
data/TODO.txt
CHANGED
data/diff_matcher.gemspec
CHANGED
Binary file
|
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
|
data/exe/diff-csv
ADDED
@@ -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
|
data/exe/diff-json
ADDED
@@ -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
|
data/exe/diff-mysql
ADDED
@@ -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}:[0m[${color}m $msg[0m" 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
|
data/lib/diff_matcher/version.rb
CHANGED
metadata
CHANGED
@@ -1,21 +1,24 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: diff_matcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- locochris
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
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:
|
@@ -28,8 +31,15 @@ files:
|
|
28
31
|
- Rakefile
|
29
32
|
- TODO.txt
|
30
33
|
- diff_matcher.gemspec
|
34
|
+
- doc/builtin_complex_matcher.png
|
31
35
|
- doc/diff_matcher.gif
|
36
|
+
- doc/diff_matcher.png
|
37
|
+
- doc/even_more_tapas_spec.rb
|
32
38
|
- doc/example_output.png
|
39
|
+
- doc/more_tapas_spec.rb
|
40
|
+
- exe/diff-csv
|
41
|
+
- exe/diff-json
|
42
|
+
- exe/diff-mysql
|
33
43
|
- lib/diff_matcher.rb
|
34
44
|
- lib/diff_matcher/difference.rb
|
35
45
|
- lib/diff_matcher/escape_to_html.rb
|
@@ -66,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
66
76
|
version: '0'
|
67
77
|
requirements: []
|
68
78
|
rubyforge_project:
|
69
|
-
rubygems_version: 2.
|
79
|
+
rubygems_version: 2.7.6
|
70
80
|
signing_key:
|
71
81
|
specification_version: 4
|
72
82
|
summary: Generates a diff by matching against user-defined matchers written in ruby.
|
@@ -74,4 +84,3 @@ test_files:
|
|
74
84
|
- spec/diff_matcher/difference_spec.rb
|
75
85
|
- spec/diff_matcher/rspec/matchers/diff_matcher_spec.rb
|
76
86
|
- spec/spec_helper.rb
|
77
|
-
has_rdoc:
|