spec_views 1.1.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +88 -5
- data/Rakefile +3 -1
- data/app/assets/config/spec_views_manifest.js +1 -0
- data/app/assets/javascripts/spec_views/diff.js +60 -0
- data/app/assets/javascripts/spec_views/jsdiff.js +1055 -0
- data/app/controllers/spec_views/views_controller.rb +18 -60
- data/app/models/spec_views/base_matcher.rb +64 -0
- data/app/models/spec_views/directory.rb +133 -0
- data/app/models/spec_views/html_matcher.rb +39 -0
- data/app/models/spec_views/http_response_extractor.rb +31 -0
- data/app/models/spec_views/mail_message_extractor.rb +30 -0
- data/app/models/spec_views/pdf_matcher.rb +49 -0
- data/app/views/layouts/spec_views.html.erb +261 -0
- data/app/views/spec_views/views/_actions.html.erb +11 -0
- data/app/views/spec_views/views/_directory_footer.html.erb +14 -0
- data/app/views/spec_views/views/compare.html.erb +11 -0
- data/app/views/spec_views/views/diff.html.erb +16 -0
- data/app/views/spec_views/views/index.html.erb +48 -0
- data/app/views/spec_views/views/preview.html.erb +32 -0
- data/config/routes.rb +3 -0
- data/lib/spec_views/configuration.rb +3 -2
- data/lib/spec_views/engine.rb +10 -0
- data/lib/spec_views/support.rb +56 -174
- data/lib/spec_views/version.rb +3 -1
- data/lib/spec_views.rb +3 -1
- data/lib/tasks/spec_views_tasks.rake +1 -0
- metadata +26 -15
- data/app/views/layouts/spec_views.html.haml +0 -200
- data/app/views/spec_views/views/compare.html.haml +0 -16
- data/app/views/spec_views/views/index.html.haml +0 -29
- data/app/views/spec_views/views/preview.html.haml +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3184a08acda31e87ed515d6f32819e70183e5ae887f430e3d21b8e84828a66fe
|
4
|
+
data.tar.gz: 7a852a0f05d557cef81590cea27faf5db52a4c82726a384823985b4a3ebf2cb2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 19c5aeeef63e2db2b68073076fca8217631241a1aa65e45f94ebacf45d141135e93f9f001c882aff5b9f2b2e62aeaa0bcf3afd38a890682256b1dfad8e53daec
|
7
|
+
data.tar.gz: 1bb5e90a3fe9fad27653d439bc6b91d140f18c0be9500125f8a2bda0573fb7f68aca301c0fef0f545a6bf6fa9e5e4f5698c91fcbd02c0ce3a4b89c86bf782f25
|
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# SpecViews
|
2
|
-
|
2
|
+
Save views from request and controller specs for comparision.
|
3
3
|
|
4
4
|
## Installation
|
5
5
|
Add this line to your application's Gemfile:
|
@@ -13,7 +13,7 @@ And this to RSpec's rails_helper.rb:
|
|
13
13
|
require 'spec_views/support'
|
14
14
|
```
|
15
15
|
|
16
|
-
|
16
|
+
Then execute:
|
17
17
|
```bash
|
18
18
|
$ bundle
|
19
19
|
```
|
@@ -25,19 +25,102 @@ Ignore some generated files in your .gitignore:
|
|
25
25
|
```
|
26
26
|
|
27
27
|
## Usage
|
28
|
-
|
28
|
+
Use the `match_html_fixture` matcher in your spec:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
RSpec.describe "Articles", type: :request do
|
32
|
+
describe 'GET /articles' do
|
33
|
+
it 'renders the listing' do
|
34
|
+
get articles_path
|
35
|
+
expect(response).to match_html_fixture
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
```
|
40
|
+
|
41
|
+
Run this spec to see it failing. Open SpecView UI [http://localhost:3000/spec_views](http://localhost:3000/spec_views) on Rails development server to accept the new view. When rerunning the spec it compares its rendering with the reference view. Use SpecView UI to review, accept or reject changed views.
|
42
|
+
|
43
|
+
### it_renders
|
44
|
+
You can also use the shortcut to skip the matcher and the word "renders" from your description:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
RSpec.describe "Articles", type: :request do
|
48
|
+
describe 'GET /articles' do
|
49
|
+
it_renders 'the listing' do
|
50
|
+
get articles_path
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
### Different response status
|
57
|
+
By default only status 200 responses are compared. Tell the matcher if your response has another one:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
RSpec.describe "Articles", type: :request do
|
61
|
+
describe 'GET /articles' do
|
62
|
+
it 'renders the listing' do
|
63
|
+
get articles_path
|
64
|
+
expect(response).to match_html_fixture.for_status(:not_found) # or 404
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
```
|
69
|
+
|
70
|
+
### PDF matching
|
71
|
+
If your request responds with a PDF you can compare it as well:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
RSpec.describe "Articles", type: :request do
|
75
|
+
describe 'GET /articles/1/download' do
|
76
|
+
it 'downloads as PDF' do
|
77
|
+
get article_path(1, format: :pdf)
|
78
|
+
expect(response).to match_pdf_fixture
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
### Mailer specs
|
85
|
+
Compare HTML mailers. `match_html_fixture` tries to find the HTML part of your mail automatically:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
RSpec.describe NotificationsMailer, :type => :mailer do
|
89
|
+
describe '#notify' do
|
90
|
+
let(:mail) { NotificationsMailer.signup }
|
91
|
+
|
92
|
+
it 'renders the body' do
|
93
|
+
expect(mail).to match_html_fixture
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
```
|
98
|
+
|
99
|
+
### Controller specs
|
100
|
+
Prefer request specs over controller specs. If you still want to use controller specs enable the `render_views` feature:
|
29
101
|
|
30
102
|
```ruby
|
31
103
|
RSpec.describe HomeController, type: :controller do
|
32
104
|
describe 'GET #show' do
|
33
|
-
|
105
|
+
render_views
|
106
|
+
|
107
|
+
it 'renders the homepage' do
|
34
108
|
get :show
|
109
|
+
expect(response).to match_html_fixture
|
35
110
|
end
|
36
111
|
end
|
37
112
|
end
|
38
113
|
```
|
39
114
|
|
40
|
-
|
115
|
+
The `it_renders` shortcuts enables `render_views` automatically.
|
116
|
+
|
117
|
+
## Configuration
|
118
|
+
Configure SpecView by adding and modifying lines to `config/environments/test.rb` and `config/environments/development.rb`:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
config.spec_views.directory = 'spec/fixtures/views'
|
122
|
+
config.spec_views.ui_url = 'http://localhost:3000/spec_views'
|
123
|
+
```
|
41
124
|
|
42
125
|
## License
|
43
126
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
begin
|
2
4
|
require 'bundler/setup'
|
3
5
|
rescue LoadError
|
@@ -14,7 +16,7 @@ RDoc::Task.new(:rdoc) do |rdoc|
|
|
14
16
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
17
|
end
|
16
18
|
|
17
|
-
APP_RAKEFILE = File.expand_path(
|
19
|
+
APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__)
|
18
20
|
load 'rails/tasks/engine.rake'
|
19
21
|
|
20
22
|
load 'rails/tasks/statistics.rake'
|
@@ -0,0 +1 @@
|
|
1
|
+
//= link spec_views/diff.js
|
@@ -0,0 +1,60 @@
|
|
1
|
+
//= require spec_views/jsdiff
|
2
|
+
|
3
|
+
var a = document.getElementById('diff-champion');
|
4
|
+
var b = document.getElementById('diff-challenger');
|
5
|
+
var result = document.getElementById('diff-result');
|
6
|
+
|
7
|
+
function changed() {
|
8
|
+
var diff = JsDiff[window.diffType](a.textContent, b.textContent);
|
9
|
+
var fragment = document.createDocumentFragment();
|
10
|
+
for (var i=0; i < diff.length; i++) {
|
11
|
+
|
12
|
+
if (diff[i].added && diff[i + 1] && diff[i + 1].removed) {
|
13
|
+
var swap = diff[i];
|
14
|
+
diff[i] = diff[i + 1];
|
15
|
+
diff[i + 1] = swap;
|
16
|
+
}
|
17
|
+
|
18
|
+
var node;
|
19
|
+
if (diff[i].removed) {
|
20
|
+
node = document.createElement('del');
|
21
|
+
node.appendChild(document.createTextNode(diff[i].value));
|
22
|
+
} else if (diff[i].added) {
|
23
|
+
node = document.createElement('ins');
|
24
|
+
node.appendChild(document.createTextNode(diff[i].value));
|
25
|
+
} else {
|
26
|
+
node = document.createTextNode(diff[i].value);
|
27
|
+
}
|
28
|
+
fragment.appendChild(node);
|
29
|
+
}
|
30
|
+
|
31
|
+
result.textContent = '';
|
32
|
+
result.appendChild(fragment);
|
33
|
+
}
|
34
|
+
|
35
|
+
window.onload = function() {
|
36
|
+
onDiffTypeChange(document.querySelector('#diff-settings [name="diff_type"]:checked'));
|
37
|
+
changed();
|
38
|
+
};
|
39
|
+
|
40
|
+
a.onpaste = a.onchange =
|
41
|
+
b.onpaste = b.onchange = changed;
|
42
|
+
|
43
|
+
if ('oninput' in a) {
|
44
|
+
a.oninput = b.oninput = changed;
|
45
|
+
} else {
|
46
|
+
a.onkeyup = b.onkeyup = changed;
|
47
|
+
}
|
48
|
+
|
49
|
+
function onDiffTypeChange(radio) {
|
50
|
+
window.diffType = radio.value;
|
51
|
+
document.title = "Diff " + radio.value.slice(4);
|
52
|
+
}
|
53
|
+
|
54
|
+
var radio = document.getElementsByName('diff_type');
|
55
|
+
for (var i = 0; i < radio.length; i++) {
|
56
|
+
radio[i].onchange = function(e) {
|
57
|
+
onDiffTypeChange(e.target);
|
58
|
+
changed();
|
59
|
+
}
|
60
|
+
}
|