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.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +88 -5
  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 -174
  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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c7f8a52383504378eddee951cba9a8fc6a47f255da78ed1a130eee0fa814ada
4
- data.tar.gz: c8fabfb166786ccb35a9ecb3b195851b04c73bea7b6fe3a0a823a3e72b963469
3
+ metadata.gz: 3184a08acda31e87ed515d6f32819e70183e5ae887f430e3d21b8e84828a66fe
4
+ data.tar.gz: 7a852a0f05d557cef81590cea27faf5db52a4c82726a384823985b4a3ebf2cb2
5
5
  SHA512:
6
- metadata.gz: 838f2fc2cb3002b3e8b3d8274ba1f1e14ea0d3fcea5d54a6ff6bdf8e9919ab37f1c3f3b8a90594ff1911bb588230d513d78a444b838452f9115120eaf71d8dc8
7
- data.tar.gz: f3fb138e0899c4a448fe2b8c3121420b6b86162a6ef3f4b5b9a81fed764e6ca3aad89c311f66381aff4d4b4a5024f87fa5c01010fb92e8621007f80fc2cb1c37
6
+ metadata.gz: 19c5aeeef63e2db2b68073076fca8217631241a1aa65e45f94ebacf45d141135e93f9f001c882aff5b9f2b2e62aeaa0bcf3afd38a890682256b1dfad8e53daec
7
+ data.tar.gz: 1bb5e90a3fe9fad27653d439bc6b91d140f18c0be9500125f8a2bda0573fb7f68aca301c0fef0f545a6bf6fa9e5e4f5698c91fcbd02c0ce3a4b89c86bf782f25
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # SpecViews
2
- Render views from controller specs for comparision.
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
- And then execute:
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
- Replace selected RSpec `it` methods with `render`:
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
- render 'homepage' do
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
- 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.
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("test/dummy/Rakefile", __dir__)
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
+ }