spec_views 1.0.1 → 2.0.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.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +101 -16
  3. data/Rakefile +3 -1
  4. data/app/assets/config/spec_views_manifest.js +1 -0
  5. data/app/assets/javascripts/spec_views/diff.js +60 -0
  6. data/app/assets/javascripts/spec_views/jsdiff.js +1055 -0
  7. data/app/controllers/spec_views/views_controller.rb +18 -60
  8. data/app/models/spec_views/base_matcher.rb +64 -0
  9. data/app/models/spec_views/directory.rb +133 -0
  10. data/app/models/spec_views/html_matcher.rb +39 -0
  11. data/app/models/spec_views/http_response_extractor.rb +31 -0
  12. data/app/models/spec_views/mail_message_extractor.rb +30 -0
  13. data/app/models/spec_views/pdf_matcher.rb +49 -0
  14. data/app/views/layouts/spec_views.html.erb +261 -0
  15. data/app/views/spec_views/views/_actions.html.erb +11 -0
  16. data/app/views/spec_views/views/_directory_footer.html.erb +14 -0
  17. data/app/views/spec_views/views/compare.html.erb +11 -0
  18. data/app/views/spec_views/views/diff.html.erb +16 -0
  19. data/app/views/spec_views/views/index.html.erb +48 -0
  20. data/app/views/spec_views/views/preview.html.erb +32 -0
  21. data/config/routes.rb +3 -0
  22. data/lib/spec_views/configuration.rb +3 -2
  23. data/lib/spec_views/engine.rb +10 -0
  24. data/lib/spec_views/support.rb +56 -166
  25. data/lib/spec_views/version.rb +3 -1
  26. data/lib/spec_views.rb +3 -1
  27. data/lib/tasks/spec_views_tasks.rake +1 -0
  28. metadata +26 -15
  29. data/app/views/layouts/spec_views.html.haml +0 -200
  30. data/app/views/spec_views/views/compare.html.haml +0 -16
  31. data/app/views/spec_views/views/index.html.haml +0 -29
  32. data/app/views/spec_views/views/preview.html.haml +0 -19
@@ -0,0 +1,261 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html>
3
+ <head>
4
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
5
+ <title>Spec Views</title>
6
+ <meta charset="utf-8"/>
7
+ <meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport"/>
8
+ <meta content="no-cache" name="turbolinks-cache-control"/>
9
+ <%= csrf_meta_tags %>
10
+ <%= csp_meta_tag %>
11
+ <style>
12
+ :root {
13
+ --dark-bg-light: #2A2D2E;
14
+ --dark-bg-lighter: #37373D;
15
+ --dark-text: #DADADA;
16
+
17
+ --accept-bg: #5fa285;
18
+ --accept-text: var(--dark-text);
19
+
20
+ --reject-bg: #d27575;
21
+ --reject-text: var(--dark-text);
22
+
23
+ --highlight: #0E639C;
24
+ --challenger: var(--highlight);
25
+ --outdated: var(--reject-bg);
26
+ }
27
+
28
+ * {
29
+ box-sizing: border-box;
30
+ margin: 0;
31
+ padding: 0;
32
+ }
33
+
34
+ body {
35
+ font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";
36
+ background: #252526;
37
+ color: #FFF;
38
+ margin: 0;
39
+ padding: 0;
40
+ }
41
+
42
+ .iframes {
43
+ position: relative;
44
+ z-index: 5;
45
+ display: flex;
46
+ justify-content: space-between;
47
+ align-items: stretch;
48
+ height: calc(100vh - 50px);
49
+ overflow: auto;
50
+ }
51
+
52
+ .iframes > * {
53
+ width: calc(50% - 5px);
54
+ height: 100%;
55
+ display: flex;
56
+ flex-direction: column;
57
+ justify-content: stretch;
58
+ }
59
+
60
+ .w-100 {
61
+ width: 100%;
62
+ }
63
+
64
+ iframe {
65
+ border: 0;
66
+ margin: 0;
67
+ padding: 0;
68
+ width: 100%;
69
+ flex-grow: 1;
70
+ }
71
+
72
+ h2 {
73
+ margin: 0;
74
+ padding: 4px 0;
75
+ text-align: center;
76
+ font-weight: 300;
77
+ text-transform: uppercase;
78
+ font-size: 12px;
79
+ line-height: 1;
80
+ }
81
+
82
+ .footer {
83
+ position: relative;
84
+ z-index: 10;
85
+ display: flex;
86
+ justify-content: space-between;
87
+ height: 50px;
88
+ box-shadow: 0px -1px 4px rgba(0, 0, 0, 0.65);
89
+ }
90
+
91
+ .info {
92
+ padding: 0 0 0 10px;
93
+ font-size: 14px;
94
+ display: flex;
95
+ align-items: center;
96
+ }
97
+ .info > div {
98
+ padding: 0.5rem 0.2rem;
99
+ }
100
+
101
+ .actions {
102
+ display: flex;
103
+ justify-content: flex-end;
104
+ padding: 2px 2rem 0 0;
105
+ }
106
+ .actions > * {
107
+ margin-left: 2rem;
108
+ }
109
+
110
+ form.button_to {
111
+ display: flex;
112
+ }
113
+
114
+ input[type=submit], .btn {
115
+ display: block;
116
+ padding: 0.5rem 0.5rem 0.4rem;
117
+ border: 0 solid var(--dark-bg-lighter);
118
+ border-width: 0 0 8px 0;
119
+ color: var(--dark-text);
120
+ border-radius: 0;
121
+ background: var(--dark-bg-light);
122
+ cursor: pointer;
123
+ font-size: 0.9rem;
124
+ line-height: 1.75;
125
+ min-width: 5rem;
126
+ text-align: center;
127
+ }
128
+ input[type=submit]:hover, .btn:hover {
129
+ background: var(--dark-bg-lighter);
130
+ }
131
+ input[type=submit].accept, .btn.accept {
132
+ border-color: var(--accept-bg);
133
+ color: var(--accept-text);
134
+ }
135
+ input[type=submit].reject, .btn.reject {
136
+ border-color: var(--reject-bg);
137
+ color: var(--reject-text);
138
+ }
139
+ input[type=submit].btn, .btn.btn {
140
+ border-color: var(--highlight);
141
+ }
142
+ input[type=submit].disabled, .btn.disabled {
143
+ opacity: 0.5;
144
+ cursor: default;
145
+ }
146
+ input[type=submit].disabled:hover, .btn.disabled:hover {
147
+ background: var(--dark-bg-light);
148
+ }
149
+
150
+ a {
151
+ color: var(--dark-text);
152
+ text-decoration: none;
153
+ }
154
+
155
+ .directories {
156
+ display: flex;
157
+ flex-direction: column;
158
+ align-items: center;
159
+ margin: 5rem auto 0;
160
+ list-style-type: none;
161
+ padding: 0;
162
+ padding-bottom: 2rem;
163
+ }
164
+ .directories > div {
165
+ margin-top: 1rem;
166
+ width: 58rem;
167
+ }
168
+ .directories > a {
169
+ display: flex;
170
+ flex: 1 0 auto;
171
+ align-items: stretch;
172
+ line-height: 1.5;
173
+ }
174
+ .directories > a:hover, .directories > a:focus {
175
+ background-color: var(--dark-bg-light);
176
+ }
177
+ .directories > a:active {
178
+ background-color: var(--dark-bg-lighter);
179
+ }
180
+ .directories > a.challenger > div:first-child {
181
+ border-color: var(--challenger);
182
+ text-align: center;
183
+ }
184
+ .directories > a.outdated > div:first-child {
185
+ border-color: var(--outdated);
186
+ text-align: center;
187
+ }
188
+ .directories > a > div {
189
+ padding: 0.5rem;
190
+ }
191
+ .directories > a > :first-child {
192
+ width: 8rem;
193
+ border: 0 solid transparent;
194
+ border-left-width: 1rem;
195
+ font-size: 0.75rem;
196
+ display: flex;
197
+ align-items: center;
198
+ }
199
+ .directories > a > :last-child {
200
+ display: flex;
201
+ flex: 1 0 auto;
202
+ width: calc(100vw - 8rem - 1rem);
203
+ align-items: center;
204
+ }
205
+ @media screen and (min-width: 1300px) {
206
+ .directories > a > :last-child {
207
+ width: 75vw;
208
+ }
209
+ }
210
+ @media screen and (min-width: 2500px) {
211
+ .directories > a > :last-child {
212
+ width: 65vw;
213
+ }
214
+ }
215
+ .directories > a > :last-child > :nth-child(1) {
216
+ flex-shrink: 0;
217
+ overflow: hidden;
218
+ text-overflow: ellipsis;
219
+ width: 15rem;
220
+ text-align: right;
221
+ }
222
+ .directories > a > :last-child > :nth-child(2) {
223
+ flex-shrink: 0;
224
+ padding: 0 1rem;
225
+ text-align: center;
226
+ width: 4rem;
227
+ }
228
+
229
+ #diff-settings {
230
+ box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.65);
231
+ margin: 0;
232
+ padding: 1rem;
233
+ }
234
+
235
+ #diff-settings span, #diff-settings label {
236
+ margin-right: 1rem;
237
+ }
238
+ #diff-settings span {
239
+ margin-right: 1rem;
240
+ }
241
+
242
+ #diff-challenger, #diff-champion {
243
+ display: none;
244
+ }
245
+
246
+ #diff-result {
247
+ margin-top: 1rem;
248
+ padding: 0 1rem;
249
+ }
250
+ #diff-result ins {
251
+ color: #9dd795;
252
+ }
253
+ #diff-result del {
254
+ color: #e39ca2;
255
+ }
256
+ </style>
257
+ </head>
258
+ <body>
259
+ <%= yield %>
260
+ </body>
261
+ </html>
@@ -0,0 +1,11 @@
1
+ <div class="actions">
2
+ <%= link_to 'Index', url_for(action: :index), class: 'index btn' %>
3
+ <% unless action_name == 'compare' %>
4
+ <%= link_to 'Compare', url_for(action: :compare), class: 'compare btn' %>
5
+ <% end %>
6
+ <% if action_name != 'diff' && diffable %>
7
+ <%= link_to 'Diff', url_for(action: :diff), class: 'diff btn' %>
8
+ <% end %>
9
+ <%= button_to 'Reject', url_for(action: :reject), class: 'reject' %>
10
+ <%= button_to 'Accept', url_for(action: :accept), class: 'accept' %>
11
+ </div>
@@ -0,0 +1,14 @@
1
+ <div class="footer">
2
+ <div class="info">
3
+ <div>
4
+ <%= directory.controller_name %>
5
+ </div>
6
+ <div>
7
+ <%= directory.method %>
8
+ </div>
9
+ <div>
10
+ <%= directory.description_tail %>
11
+ </div>
12
+ </div>
13
+ <%= render 'actions', diffable: !directory.binary? %>
14
+ </div>
@@ -0,0 +1,11 @@
1
+ <div class="iframes">
2
+ <div>
3
+ <h2>Champion</h2>
4
+ <iframe src="<%= url_for(action: :show) %>"></iframe>
5
+ </div>
6
+ <div>
7
+ <h2>Challenger</h2>
8
+ <iframe src="<%= url_for(action: :show, view: :challenger) %>"></iframe>
9
+ </div>
10
+ </div>
11
+ <%= render 'directory_footer', directory: @directory %>
@@ -0,0 +1,16 @@
1
+ <div class="iframes">
2
+ <div class="w-100">
3
+ <div id="diff-settings">
4
+ <span>Diff</span>
5
+ <label><input type="radio" name="diff_type" value="diffChars" checked> Characters</label>
6
+ <label><input type="radio" name="diff_type" value="diffWords"> Words</label>
7
+ <label><input type="radio" name="diff_type" value="diffLines"> Lines</label>
8
+ </div>
9
+ <div id="diff-champion"><%= @champion %></div>
10
+ <div id="diff-challenger"><%= @challenger %></div>
11
+ <pre id="diff-result"></pre>
12
+ </div>
13
+ </div>
14
+ <%= render 'directory_footer', directory: @directory %>
15
+
16
+ <%= javascript_include_tag 'spec_views/diff' %>
@@ -0,0 +1,48 @@
1
+ <div class="iframes">
2
+ <div class="w-100">
3
+ <div class="directories">
4
+ <% @directories.each do |dir| %>
5
+ <% body = capture do %>
6
+ <div>
7
+ <div>
8
+ <%= dir.controller_name %>
9
+ </div>
10
+ <div>
11
+ <%= dir.method %>
12
+ </div>
13
+ <div>
14
+ <%= dir.description_tail %>
15
+ </div>
16
+ </div>
17
+ <% end %>
18
+ <% if dir.challenger? %>
19
+ <%= link_to({ action: :compare, id: dir }, class: 'challenger') do %>
20
+ <div>CHALLENGER</div>
21
+ <%= body %>
22
+ <% end %>
23
+ <% elsif dir.last_run < @latest_run %>
24
+ <%= link_to({ action: :preview, id: dir }, class: 'outdated') do %>
25
+ <div>OUTDATED</div>
26
+ <%= body %>
27
+ <% end %>
28
+ <% else %>
29
+ <%= link_to(action: :preview, id: dir) do %>
30
+ <div></div>
31
+ <%= body %>
32
+ <% end %>
33
+ <% end %>
34
+ <% end %>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ <div class="footer">
39
+ <div class="info"></div>
40
+ <div class="actions">
41
+ <% if @directories.any?{ |dir| dir.last_run < @latest_run } %>
42
+ <%= button_to 'Remove Outdated', url_for(action: :destroy_outdated), method: :delete, class: 'reject' %>
43
+ <% end %>
44
+ <% if @directories.any?(&:challenger?) %>
45
+ <%= button_to 'Accept All', url_for(action: :accept_all), method: :post, class: 'accept' %>
46
+ <% end %>
47
+ </div>
48
+ </div>
@@ -0,0 +1,32 @@
1
+ <div class="iframes">
2
+ <div class="w-100">
3
+ <h2>Champion</h2>
4
+ <iframe src="<%= url_for(action: :show) %>"></iframe>
5
+ </div>
6
+ </div>
7
+ <div class="footer">
8
+ <div class="info">
9
+ <div>
10
+ <%= @directory.controller_name %>
11
+ </div>
12
+ <div>
13
+ <%= @directory.method %>
14
+ </div>
15
+ <div>
16
+ <%= @directory.description_tail %>
17
+ </div>
18
+ </div>
19
+ <div class="actions">
20
+ <%= link_to 'Index', url_for(action: :index), class: 'index btn' %>
21
+ <% if @previous %>
22
+ <%= link_to 'Previous', url_for(action: :preview, id: @previous), class: 'previous btn', disabled: true %>
23
+ <% else %>
24
+ <span class="previous btn disabled">Previous</span>
25
+ <% end %>
26
+ <% if @next %>
27
+ <%= link_to 'Next', url_for(action: :preview, id: @next), class: 'next btn' %>
28
+ <% else %>
29
+ <span class="previous btn disabled">Next</span>
30
+ <% end %>
31
+ </div>
32
+ </div>
data/config/routes.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Rails.application.routes.draw do
2
4
  namespace :spec_views do
3
5
  root to: redirect('spec_views/views')
@@ -9,6 +11,7 @@ Rails.application.routes.draw do
9
11
  end
10
12
  member do
11
13
  get :compare
14
+ get :diff
12
15
  get :preview
13
16
  post :accept
14
17
  post :reject
@@ -4,8 +4,9 @@ module SpecViews
4
4
  class Configuration < ActiveSupport::InheritableOptions
5
5
  def self.default
6
6
  new(
7
- directory: 'spec/fixtures/views'
7
+ directory: 'spec/fixtures/views',
8
+ ui_url: 'http://localhost:3000/spec_views'
8
9
  )
9
10
  end
10
11
  end
11
- end
12
+ end
@@ -1,7 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_views/configuration'
2
4
 
3
5
  module SpecViews
4
6
  class Engine < ::Rails::Engine
5
7
  config.spec_views = Configuration.default
8
+
9
+ initializer 'spec_views.assets.precompile' do |app|
10
+ app.config.assets.precompile += %w[spec_views/diff.js]
11
+ end
12
+
13
+ config.generators do |g|
14
+ g.test_framework :rspec
15
+ end
6
16
  end
7
17
  end
@@ -1,186 +1,76 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'timecop'
4
+
3
5
  module SpecViews
4
6
  module Support
5
- class SpecView
6
- attr_reader :body, :context, :example, :spec_name, :directory_path, :last_run_path,
7
- :time, :response
8
-
9
- class ReadError < StandardError
10
- def initialize(msg = 'My default message')
11
- super
12
- end
13
- end
14
-
15
- def initialize(context, example, response, time)
16
- @context = context
17
- @response = response
18
- @example = example
19
- @spec_name = example.full_description.strip
20
- .gsub(/[^0-9A-Za-z.\-]/, '_').gsub('__', '_')
21
- @spec_name = "#{@spec_name}__pdf" if pdf?
22
- @directory_path = Rails.root.join(Rails.configuration.spec_views.directory, spec_name)
23
- @last_run_path = directory_path.join('last_run.txt')
24
- @body = response.body
25
- @time = time
26
- end
27
-
28
- def write
29
- FileUtils.mkdir_p(directory_path)
30
- write_to_path(champion_path, sanitized_body)
31
- put_write_instructions
32
- end
33
-
34
- def write_challenger
35
- return unless changed?
36
-
37
- FileUtils.mkdir_p(directory_path)
38
- write_to_path(challenger_path, sanitized_body)
39
- end
40
-
41
- def delete_challenger
42
- FileUtils.rm_f(challenger_path) unless changed?
43
- end
44
-
45
- def write_last_run
46
- FileUtils.mkdir_p(directory_path)
47
- write_to_path(last_run_path, time)
48
- end
49
-
50
- def expect_eq
51
- pdf? ? expect_eq_pdf : expect_eq_text
52
- delete_challenger
53
- end
54
-
55
- def expect_eq_text
56
- context.expect(sanitized_body).to context.eq(read)
57
- end
58
-
59
- def expect_eq_pdf
60
- champion_md5 = nil
61
- begin
62
- champion_md5 = Digest::MD5.file(champion_path).hexdigest
63
- rescue Errno::ENOENT # rubocop:disable Lint/SuppressedException
64
- end
65
- current_md5 = Digest::MD5.hexdigest(sanitized_body)
66
- context.expect(current_md5).to context.eq(champion_md5), 'MD5s of PDF do not match'
67
- end
68
-
69
- def read
70
- File.read(champion_path)
71
- rescue Errno::ENOENT
72
- raise ReadError, "Cannot find view fixture #{champion_path.to_s.gsub(Rails.root.to_s, '')}\n" \
73
- "Create the file by adding the follwing to your spec:\n" \
74
- 'spec_view.write'
75
- end
76
-
77
- def changed?
78
- return pdf_changed? if pdf?
79
-
80
- begin
81
- champion = read
82
- rescue ReadError
83
- champion = nil
84
- end
85
- sanitized_body != champion
86
- end
87
-
88
- def pdf_changed?
89
- champion_md5 = Digest::MD5.file(champion_path).hexdigest
90
- current_md5 = Digest::MD5.hexdigest(sanitized_body)
91
- champion_md5 != current_md5
92
- rescue Errno::ENOENT
93
- true
94
- end
95
-
96
- private
97
-
98
- def champion_path
99
- pdf? ? directory_path.join('view.pdf') : directory_path.join('view.html')
100
- end
101
-
102
- def challenger_path
103
- pdf? ? directory_path.join('challenger.pdf') : directory_path.join('challenger.html')
104
- end
105
-
106
- def sanitized_body
107
- return body if pdf?
108
-
109
- remove_pack_digests_from_body(
110
- remove_digests_from_body(body),
111
- )
112
- end
113
-
114
- def remove_digests_from_body(body)
115
- body.gsub(/(-[a-z0-9]{64})(\.css|\.js|\.png|\.jpg|\.jpeg|\.svg|\.gif)/, '\2')
116
- end
117
-
118
- def remove_pack_digests_from_body(body)
119
- body.gsub(%r{(packs.*/js/[a-z0-9_]+)(-[a-z0-9]{20})(\.js)}, '\1\3')
120
- end
121
-
122
- def put_write_instructions
123
- puts
124
- puts "\e[33mWarning:\e[0m Writing view fixture to #{champion_path.to_s.gsub(Rails.root.to_s, '')}"
125
- puts 'xdg-open "http://localhost:3100/spec_views/"'
126
- end
127
-
128
- def write_to_path(path, content)
129
- File.open(path.to_s, pdf? ? 'wb' : 'w') do |file|
130
- file.write(content)
131
- end
132
- end
133
-
134
- def pdf?
135
- response.content_type == 'application/pdf'
136
- end
137
- end
138
-
139
- def spec_view
140
- SpecView.new(self, @_spec_view_example, response, $_spec_view_time)
141
- end
142
-
143
7
  module SpecViewExample
144
- def render(description = nil, focus: nil, pending: nil, status: :ok, &block)
145
- context do # rubocop:disable RSpec/MissingExampleGroupArgument
146
- render_views
8
+ def it_renders(description = nil, focus: nil, pending: nil, status: :ok, &block)
9
+ context do
10
+ render_views if respond_to?(:render_views)
147
11
  options = {}
148
12
  options[:focus] = focus unless focus.nil?
149
13
  options[:pending] = pending unless pending.nil?
14
+ description = "renders #{description}" if description.is_a?(String)
150
15
  it(description, options) do
151
16
  instance_eval(&block)
152
- spec_view.write_last_run
153
- write = status.in?(
154
- [
155
- response.message.parameterize.underscore.to_sym,
156
- response.status,
157
- ],
158
- )
159
- spec_view.write_challenger if write
160
- spec_view.expect_eq
17
+ expect(response).to match_html_fixture.for_status(status)
161
18
  end
162
19
  end
163
20
  end
164
21
  end
22
+ end
23
+ end
165
24
 
166
- RSpec.configure do |c|
167
- c.extend SpecViewExample, type: :controller
168
- c.before(:suite) do |_example|
169
- $_spec_view_time = Time.zone.now
170
- end
171
- c.before(type: :controller) do |example|
172
- @_spec_view_example = example
173
- end
174
- c.before(:each, type: :controller) do
175
- Timecop.freeze(Time.zone.local(2024, 2, 29, 0o0, 17, 42))
176
- end
177
- c.after(:each, type: :controller) do
178
- Timecop.return
179
- end
25
+ RSpec.configure do |c|
26
+ c.before(:suite) do |_example|
27
+ $_spec_view_time = Time.zone.now # rubocop:disable Style/GlobalVars
28
+ end
29
+ %i[controller mailer request].each do |type|
30
+ c.extend SpecViews::Support::SpecViewExample, type: type
31
+ c.before(type: type) do |example|
32
+ @_spec_view_example = example
33
+ end
34
+ c.before(:each, type: type) do
35
+ Timecop.freeze(Time.zone.local(2024, 2, 29, 0o0, 17, 42))
36
+ end
37
+ c.after(:each, type: type) do
38
+ Timecop.return
180
39
  end
181
40
  end
182
41
  end
183
42
 
184
- RSpec.configure do |rspec|
185
- rspec.include SpecViews::Support, type: :controller
43
+
44
+ matchers = [
45
+ [:match_html_fixture, SpecViews::HtmlMatcher],
46
+ [:match_pdf_fixture, SpecViews::PdfMatcher]
47
+ ]
48
+
49
+ matchers.each do |matcher|
50
+ RSpec::Matchers.define matcher.first do |_expected|
51
+ chain :for_status do |status|
52
+ @status = status
53
+ end
54
+
55
+ match do |actual|
56
+ example = @matcher_execution_context.instance_variable_get('@_spec_view_example')
57
+ description = example.full_description
58
+ type = example.metadata[:type]
59
+ run_time = $_spec_view_time # rubocop:disable Style/GlobalVars
60
+ @status ||= :ok
61
+ @matcher = matcher.second.new(
62
+ actual,
63
+ description,
64
+ expected_status: @status,
65
+ run_time: run_time,
66
+ type: type
67
+ )
68
+ return @matcher.match?
69
+ end
70
+
71
+ failure_message do |_actual|
72
+ "#{@matcher.failure_message} " \
73
+ "Review the challenger: #{Rails.configuration.spec_views.ui_url}"
74
+ end
75
+ end
186
76
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SpecViews
2
- VERSION = '1.0.1'
4
+ VERSION = '2.0.0'
3
5
  end