spec_views 3.4.0 → 3.6.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 +4 -4
- data/README.md +17 -0
- data/app/models/spec_views/base_matcher.rb +7 -0
- data/app/models/spec_views/html_matcher.rb +70 -0
- data/lib/spec_views/support.rb +4 -0
- data/lib/spec_views/version.rb +1 -1
- data/lib/tasks/spec_views_tasks.rake +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b4862f0d853b34af72a88330522aa151badd6e4b2379d7c48cbcd762f74bcfe9
|
|
4
|
+
data.tar.gz: bc86734dc64a77d10e3ea0d9ded7fb4ac6382b3a3b134b4cba0ccf8a4ca95d87
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8680677d0d527f89f09e18dfdd71a1ae9d85b5e17341aa0823ce94a792b43d35e7b9bab21a6936f70ca0419485823fad817bb4e967fe04728d303458570430cd
|
|
7
|
+
data.tar.gz: 72a5abde93d36f10cac9b998b4271e93224062277848d9cadd6f3041402babcba56787abc234b64eb03817004ac3fb7189ac06b8fafb6d940d5a1f9b3177608c
|
data/README.md
CHANGED
|
@@ -79,6 +79,23 @@ RSpec.describe "Articles", type: :request do
|
|
|
79
79
|
end
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
+
### Add an affix
|
|
83
|
+
If you have two requests with the same description, you can add an affix to the generated name:
|
|
84
|
+
|
|
85
|
+
```ruby
|
|
86
|
+
RSpec.describe "Articles", type: :request do
|
|
87
|
+
describe 'GET /articles' do
|
|
88
|
+
it 'renders the listing' do
|
|
89
|
+
get articles_path
|
|
90
|
+
expect(response).to match_html_fixture.with_affix('only 10')
|
|
91
|
+
|
|
92
|
+
get articles_path(all: '1')
|
|
93
|
+
expect(response).to match_html_fixture.with_affix('all')
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
```
|
|
98
|
+
|
|
82
99
|
### PDF matching
|
|
83
100
|
If your request responds with a PDF you can compare it as well:
|
|
84
101
|
|
|
@@ -25,6 +25,9 @@ module SpecViews
|
|
|
25
25
|
@failure_message = "#{subject_name} has changed."
|
|
26
26
|
@failure_message = "#{subject_name} has been added." if champion_html.nil?
|
|
27
27
|
|
|
28
|
+
preview = diff_preview
|
|
29
|
+
@failure_message += preview if preview.present?
|
|
30
|
+
|
|
28
31
|
directory.write_last_run(run_time)
|
|
29
32
|
directory.write_meta(description, type, content_type)
|
|
30
33
|
@directory.write_challenger(challenger_body)
|
|
@@ -56,6 +59,10 @@ module SpecViews
|
|
|
56
59
|
raise NotImplementedError
|
|
57
60
|
end
|
|
58
61
|
|
|
62
|
+
def diff_preview
|
|
63
|
+
nil
|
|
64
|
+
end
|
|
65
|
+
|
|
59
66
|
def extractor_class
|
|
60
67
|
return CapybaraSessionExtractor if type == :feature
|
|
61
68
|
return MailMessageExtractor if type == :mailer
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'diff/lcs'
|
|
4
|
+
|
|
3
5
|
module SpecViews
|
|
4
6
|
class HtmlMatcher < BaseMatcher
|
|
5
7
|
delegate :champion_html, to: :directory
|
|
@@ -22,6 +24,40 @@ module SpecViews
|
|
|
22
24
|
champion_html == challenger_body
|
|
23
25
|
end
|
|
24
26
|
|
|
27
|
+
def diff_preview
|
|
28
|
+
return nil unless champion_html.present?
|
|
29
|
+
|
|
30
|
+
champion_lines = champion_html.lines
|
|
31
|
+
challenger_lines = challenger_body.lines
|
|
32
|
+
|
|
33
|
+
diffs = Diff::LCS.diff(champion_lines, challenger_lines)
|
|
34
|
+
return nil if diffs.empty?
|
|
35
|
+
|
|
36
|
+
first_change = diffs.first.first
|
|
37
|
+
line_number = first_change.position + 1
|
|
38
|
+
|
|
39
|
+
preview = "\nFirst difference at line #{line_number}:\n"
|
|
40
|
+
|
|
41
|
+
if first_change.action == '-'
|
|
42
|
+
old_line = first_change.element.chomp
|
|
43
|
+
addition = diffs.first.find { |change| change.action == '+' && change.position == first_change.position }
|
|
44
|
+
|
|
45
|
+
if addition
|
|
46
|
+
new_line = addition.element.chomp
|
|
47
|
+
truncated_old, truncated_new, marker_pos = truncate_diff_lines_with_marker(old_line, new_line)
|
|
48
|
+
preview += " - #{truncated_old}\n"
|
|
49
|
+
preview += " + #{truncated_new}\n"
|
|
50
|
+
preview += " #{' ' * marker_pos}^\n" if marker_pos
|
|
51
|
+
else
|
|
52
|
+
preview += " - #{truncate_line(old_line)}\n"
|
|
53
|
+
end
|
|
54
|
+
elsif first_change.action == '+'
|
|
55
|
+
preview += " + #{truncate_line(first_change.element.chomp)}\n"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
preview
|
|
59
|
+
end
|
|
60
|
+
|
|
25
61
|
private
|
|
26
62
|
|
|
27
63
|
def sanitized_body
|
|
@@ -37,5 +73,39 @@ module SpecViews
|
|
|
37
73
|
def remove_pack_digests_from_body(body)
|
|
38
74
|
body.gsub(%r{(packs.*/js/[a-z0-9_]+)(-[a-z0-9]{20})(\.js)}, '\1\3')
|
|
39
75
|
end
|
|
76
|
+
|
|
77
|
+
def truncate_diff_lines_with_marker(old_line, new_line, max_common_prefix: 10, max_length: 100)
|
|
78
|
+
common_length = 0
|
|
79
|
+
[old_line.length, new_line.length].min.times do |i|
|
|
80
|
+
break if old_line[i] != new_line[i]
|
|
81
|
+
|
|
82
|
+
common_length = i + 1
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
prefix_offset = 0
|
|
86
|
+
prefix_marker = ''
|
|
87
|
+
if common_length > max_common_prefix
|
|
88
|
+
prefix_offset = common_length - max_common_prefix
|
|
89
|
+
prefix_marker = '...'
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
old_relevant = prefix_marker + old_line[prefix_offset..]
|
|
93
|
+
new_relevant = prefix_marker + new_line[prefix_offset..]
|
|
94
|
+
|
|
95
|
+
marker_pos = prefix_marker.length + (common_length - prefix_offset)
|
|
96
|
+
|
|
97
|
+
truncated_old = truncate_line(old_relevant, max_length)
|
|
98
|
+
truncated_new = truncate_line(new_relevant, max_length)
|
|
99
|
+
|
|
100
|
+
marker_pos = nil if marker_pos >= max_length
|
|
101
|
+
|
|
102
|
+
[truncated_old, truncated_new, marker_pos]
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def truncate_line(line, max_length = 100)
|
|
106
|
+
return line if line.length <= max_length
|
|
107
|
+
|
|
108
|
+
"#{line[0...max_length]}..."
|
|
109
|
+
end
|
|
40
110
|
end
|
|
41
111
|
end
|
data/lib/spec_views/support.rb
CHANGED
|
@@ -55,10 +55,14 @@ matchers.each do |matcher|
|
|
|
55
55
|
chain :for_status do |status|
|
|
56
56
|
@status = status
|
|
57
57
|
end
|
|
58
|
+
chain :with_affix do |affix|
|
|
59
|
+
@affix = affix
|
|
60
|
+
end
|
|
58
61
|
|
|
59
62
|
match do |actual|
|
|
60
63
|
example = @matcher_execution_context.instance_variable_get('@_spec_view_example')
|
|
61
64
|
description = example.full_description
|
|
65
|
+
description = "#{description}-#{@affix}" if @affix.present?
|
|
62
66
|
type = example.metadata[:type]
|
|
63
67
|
run_time = $_spec_view_time # rubocop:disable Style/GlobalVars
|
|
64
68
|
@status ||= :ok
|
data/lib/spec_views/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: spec_views
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sebastian Gaul
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2025-11-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: diff-lcs
|