react_on_rails 1.1.1 → 1.2.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +1 -0
  4. data/.travis.yml +2 -8
  5. data/Dockerfile_tests +1 -1
  6. data/Gemfile +68 -2
  7. data/README.md +21 -15
  8. data/Rakefile +3 -109
  9. data/app/assets/javascripts/react_on_rails.js +10 -0
  10. data/docker-compose.yml +0 -6
  11. data/docs/additional_reading/webpack.md +46 -0
  12. data/docs/generator_testing.md +20 -0
  13. data/lib/generators/react_on_rails/base_generator.rb +49 -9
  14. data/lib/generators/react_on_rails/bootstrap_generator.rb +14 -29
  15. data/lib/generators/react_on_rails/dev_tests_generator.rb +30 -0
  16. data/lib/generators/react_on_rails/install_generator.rb +14 -3
  17. data/lib/generators/react_on_rails/templates/base/base/app/views/hello_world/index.html.erb.tt +2 -3
  18. data/lib/generators/react_on_rails/templates/base/base/client/package.json.tt +26 -23
  19. data/lib/generators/react_on_rails/templates/base/base/client/{webpack.client.hot.config.js → webpack.client.hot.config.js.tt} +3 -1
  20. data/lib/generators/react_on_rails/templates/base/base/lib/tasks/{assets.rake → assets.rake.tt} +2 -0
  21. data/lib/generators/react_on_rails/templates/base/server_rendering/client/webpack.server.rails.config.js +1 -1
  22. data/lib/generators/react_on_rails/templates/dev_tests/.rspec +2 -0
  23. data/lib/generators/react_on_rails/templates/dev_tests/spec/features/hello_world_spec.rb +25 -0
  24. data/lib/generators/react_on_rails/templates/dev_tests/spec/rails_helper.rb +57 -0
  25. data/lib/generators/react_on_rails/templates/dev_tests/spec/simplecov_helper.rb +21 -0
  26. data/lib/generators/react_on_rails/templates/dev_tests/spec/spec_helper.rb +95 -0
  27. data/lib/react_on_rails/version.rb +1 -1
  28. data/rakelib/docker.rake +33 -0
  29. data/rakelib/dummy_apps.rake +29 -0
  30. data/rakelib/example_type.rb +160 -0
  31. data/rakelib/examples.rake +103 -0
  32. data/rakelib/examples_config.yml +19 -0
  33. data/rakelib/lint.rake +37 -0
  34. data/rakelib/run_rspec.rake +65 -0
  35. data/rakelib/task_helpers.rb +44 -0
  36. data/ruby-lint.yml +1 -0
  37. metadata +22 -9
  38. data/Dockerfile_ci +0 -12
  39. data/docs/generator_testing_script.md +0 -49
  40. data/lib/generators/react_on_rails/templates/client/README.md +0 -97
@@ -0,0 +1,20 @@
1
+ # Generator Testing
2
+ We create several applications that are examples of running the generator (see lib/generators/react_on_rails/install_generator.rb) with various different options. We can then run tests with these apps just like we would any Rails app and thus ensure that our generator makes apps that actually function properly.
3
+
4
+ Special rake tasks in rakelib/examples.rake handle creating the example apps and running a special hidden generator (lib/generators/react_on_rails/dev_tests_generator.rb) that installs the tests we want to run for each app. These tests can be run manually like any Rails app, or they can be run via the `rake run_rspec:examples` command. There are also commands for running each app individually, i.e., `rake run_rspec:example_basic`.
5
+
6
+ ## Travis and Gemfiles
7
+ We are currently using Travis for CI. Because of the way Travis works, it is not possible to `bundle install` multiple Gemfiles. Therefore, we have placed all dependencies for generated apps in the gem's main Gemfile. If you generate an app that has a new gem dependency in its Gemfile, you need to add that dependency to the main Gemfile or it will not work in CI.
8
+
9
+ ## Configuring what Apps are Generated
10
+ You can specify additional apps to generate and test by adding to the rakelib/examples_config.yml file. The necessary build and test tasks will automatically be created for you dynamically at runtime.
11
+
12
+ ## More on the Rake Tasks
13
+ In order to maximize efficiency, we took several steps to improve the performance of the rake tasks that utilize somewhat advanced rake functionality such as task dependencies, `file` tasks, task synthesizing, and concurrent tasks with `multitask`.
14
+
15
+ For example, re-generating the app, running `npm install`, and re-generating the webpack bundles are all only done when they need to be done. Rake will also run certain tasks, including those that generate multiple applications, concurrently. When running `npm install`, this may produce strange-looking output due to the way the npm's console progress bar works. This is normal.
16
+
17
+ For more insight, see:
18
+
19
+ - [Avdi Grimm's series of articles on Rake](http://devblog.avdi.org/2014/04/30/learn-advanced-rake-in-7-episodes/)
20
+ - [Martin Fowler's rake article](http://martinfowler.com/articles/rake.html)
@@ -1,5 +1,6 @@
1
1
  require "rails/generators"
2
2
  require File.expand_path("../generator_helper", __FILE__)
3
+
3
4
  include GeneratorHelper
4
5
 
5
6
  module ReactOnRails
@@ -33,6 +34,13 @@ module ReactOnRails
33
34
  desc: "Install ruby linting files, tasks, and configs",
34
35
  aliases: "-L"
35
36
 
37
+ # --skip-bootstrap
38
+ class_option :skip_bootstrap,
39
+ type: :boolean,
40
+ default: false,
41
+ desc: "Skip integrating Bootstrap and don't initialize files and regarding configs",
42
+ aliases: "-b"
43
+
36
44
  def add_hello_world_route
37
45
  route "get 'hello_world', to: 'hello_world#index'"
38
46
  end
@@ -69,9 +77,6 @@ module ReactOnRails
69
77
  //= require generated/vendor-bundle
70
78
  //= require generated/app-bundle
71
79
 
72
- // bootstrap-sprockets depends on generated/vendor-bundle for jQuery.
73
- //= require bootstrap-sprockets
74
-
75
80
  DATA
76
81
 
77
82
  app_js_path = "app/assets/javascripts/application.js"
@@ -85,9 +90,9 @@ module ReactOnRails
85
90
 
86
91
  def strip_application_js_of_incompatible_sprockets_statements
87
92
  application_js = File.join(destination_root, "app/assets/javascripts/application.js")
88
- gsub_file(application_js, "//= require jquery_ujs", "")
89
- gsub_file(application_js, %r{//= require jquery$}, "")
90
- gsub_file(application_js, "//= require_tree .", "")
93
+ gsub_file(application_js, "//= require jquery_ujs", "// require jquery_ujs")
94
+ gsub_file(application_js, %r{//= require jquery$}, "// require jquery")
95
+ gsub_file(application_js, %r{//= require_tree \.$}, "// require_tree .")
91
96
  end
92
97
 
93
98
  def strip_application_js_of_double_blank_lines
@@ -106,11 +111,8 @@ module ReactOnRails
106
111
  config/initializers/react_on_rails.rb
107
112
  client/.babelrc
108
113
  client/index.jade
109
- client/npm-shrinkwrap.json
110
114
  client/server.js
111
- client/webpack.client.hot.config.js
112
115
  client/webpack.client.rails.config.js
113
- lib/tasks/assets.rake
114
116
  REACT_ON_RAILS.md
115
117
  client/REACT_ON_RAILS_CLIENT_README.md
116
118
  package.json).each { |file| copy_file(base_path + file, file) }
@@ -121,10 +123,12 @@ module ReactOnRails
121
123
  %w(Procfile.dev
122
124
  app/views/hello_world/index.html.erb
123
125
  client/webpack.client.base.config.js
126
+ client/webpack.client.hot.config.js
124
127
  client/package.json).each { |file| template(base_path + file + ".tt", file) }
125
128
  end
126
129
 
127
130
  def add_base_gems_to_gemfile
131
+ return unless options.server_rendering?
128
132
  append_to_file("Gemfile", "\ngem 'therubyracer', platforms: :ruby\n")
129
133
  end
130
134
 
@@ -147,6 +151,42 @@ module ReactOnRails
147
151
  return if !options.ruby_linters? && options.skip_js_linters?
148
152
  template("base/base/lib/tasks/linters.rake.tt", "lib/tasks/linters.rake")
149
153
  end
154
+
155
+ def template_assets_rake_file
156
+ template("base/base/lib/tasks/assets.rake.tt", "lib/tasks/assets.rake")
157
+ end
158
+
159
+ def append_to_assets_initializer
160
+ data = <<-DATA.strip_heredoc
161
+ # Add client/assets/ folders to asset pipeline's search path.
162
+ # If you do not want to move existing images and fonts from your Rails app
163
+ # you could also consider creating symlinks there that point to the original
164
+ # rails directories. In that case, you would not add these paths here.
165
+ Rails.application.config.assets.paths << Rails.root.join("client", "assets", "stylesheets")
166
+ Rails.application.config.assets.paths << Rails.root.join("client", "assets", "images")
167
+ Rails.application.config.assets.paths << Rails.root.join("client", "assets", "fonts")
168
+ Rails.application.config.assets.precompile += %w( generated/server-bundle.js )
169
+ DATA
170
+ assets_intializer = File.join(destination_root, "config/initializers/assets.rb")
171
+ if File.exist?(assets_intializer)
172
+ append_to_file(assets_intializer, data)
173
+ else
174
+ create_file(assets_intializer, data)
175
+ end
176
+ end
177
+
178
+ # rename to application.scss from application.css or application.css.scss
179
+ def force_application_scss_naming_if_necessary
180
+ base_path = "app/assets/stylesheets/"
181
+ application_css = "#{base_path}application.css"
182
+ application_css_scss = "#{base_path}application.css.scss"
183
+
184
+ bad_name = dest_file_exists?(application_css) || dest_file_exists?(application_css_scss)
185
+ return unless bad_name
186
+
187
+ new_name = File.join(destination_root, "#{base_path}application.scss")
188
+ File.rename(bad_name, new_name)
189
+ end
150
190
  end
151
191
  end
152
192
  end
@@ -8,21 +8,6 @@ module ReactOnRails
8
8
  hide!
9
9
  source_root(File.expand_path("../templates", __FILE__))
10
10
 
11
- def append_to_assets_initializer
12
- data = <<-DATA.strip_heredoc
13
- # Add client/assets/ folders to asset pipeline's search path.
14
- # If you do not want to move existing images and fonts from your Rails app
15
- # you could also consider creating symlinks there that point to the original
16
- # rails directories. In that case, you would not add these paths here.
17
- Rails.application.config.assets.paths << Rails.root.join("client", "assets", "stylesheets")
18
- Rails.application.config.assets.paths << Rails.root.join("client", "assets", "images")
19
- Rails.application.config.assets.paths << Rails.root.join("client", "assets", "fonts")
20
-
21
- Rails.application.config.assets.precompile += %w( generated/server-bundle.js )
22
- DATA
23
- append_to_file("config/initializers/assets.rb", data)
24
- end
25
-
26
11
  def copy_bootstrap_files
27
12
  base_path = "bootstrap/"
28
13
  %w(app/assets/stylesheets/_bootstrap-custom.scss
@@ -32,19 +17,6 @@ module ReactOnRails
32
17
  client/bootstrap-sass.config.js).each { |file| copy_file(base_path + file, file) }
33
18
  end
34
19
 
35
- # rename to application.scss from application.css or application.css.scss
36
- def force_application_scss_naming_if_necessary
37
- base_path = "app/assets/stylesheets/"
38
- application_css = "#{base_path}application.css"
39
- application_css_scss = "#{base_path}application.css.scss"
40
-
41
- bad_name = dest_file_exists?(application_css) || dest_file_exists?(application_css_scss)
42
- return unless bad_name
43
-
44
- new_name = File.join(destination_root, "#{base_path}application.scss")
45
- File.rename(bad_name, new_name)
46
- end
47
-
48
20
  # if there still is not application.scss, just create one
49
21
  def create_application_scss_if_necessary
50
22
  path = File.join(destination_root, "app/assets/stylesheets/application.scss")
@@ -97,7 +69,20 @@ module ReactOnRails
97
69
  end
98
70
 
99
71
  def add_bootstrap_sprockets_to_application_js
100
- # see base_generator.rb this is done there
72
+ data = <<-DATA.strip_heredoc
73
+
74
+ // bootstrap-sprockets depends on generated/vendor-bundle for jQuery.
75
+ //= require bootstrap-sprockets
76
+
77
+ DATA
78
+
79
+ app_js_path = "app/assets/javascripts/application.js"
80
+ found_app_js = dest_file_exists?(app_js_path) || dest_file_exists?(app_js_path + ".coffee")
81
+ if found_app_js
82
+ append_to_file(found_app_js, data)
83
+ else
84
+ create_file(app_js_path, data)
85
+ end
101
86
  end
102
87
  end
103
88
  end
@@ -0,0 +1,30 @@
1
+ require "rails/generators"
2
+ require_relative "generator_helper"
3
+ include GeneratorHelper
4
+
5
+ module ReactOnRails
6
+ module Generators
7
+ class DevTestsGenerator < Rails::Generators::Base
8
+ hide!
9
+ source_root(File.expand_path("../templates/dev_tests", __FILE__))
10
+
11
+ def copy_rspec_files
12
+ %w(spec/spec_helper.rb
13
+ spec/rails_helper.rb
14
+ spec/simplecov_helper.rb
15
+ .rspec).each { |file| copy_file(file) }
16
+ end
17
+
18
+ def copy_tests
19
+ %w(spec/features/hello_world_spec.rb).each { |file| copy_file(file) }
20
+ end
21
+
22
+ def add_test_related_gems_to_gemfile
23
+ gem("rspec-rails", group: :test)
24
+ gem("capybara", group: :test)
25
+ gem("selenium-webdriver", group: :test)
26
+ gem("coveralls", require: false)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -34,20 +34,31 @@ module ReactOnRails
34
34
  desc: "Install files necessary for deploying to Heroku",
35
35
  aliases: "-H"
36
36
 
37
+ # --skip-bootstrap
38
+ class_option :skip_bootstrap,
39
+ type: :boolean,
40
+ default: false,
41
+ desc: "Skip integrating Bootstrap and don't initialize files and regarding configs",
42
+ aliases: "-b"
43
+
37
44
  def run_generators # rubocop:disable Metrics/CyclomaticComplexity
38
45
  return unless installation_prerequisites_met?
39
46
  warn_if_nvm_is_not_installed
47
+ invoke_generators
48
+ end
49
+
50
+ private
51
+
52
+ def invoke_generators # rubocop:disable Metrics/CyclomaticComplexity
40
53
  invoke "react_on_rails:base"
41
54
  invoke "react_on_rails:react_no_redux" unless options.redux?
42
55
  invoke "react_on_rails:react_with_redux" if options.redux?
43
56
  invoke "react_on_rails:js_linters" unless options.skip_js_linters?
44
57
  invoke "react_on_rails:ruby_linters" if options.ruby_linters?
45
- invoke "react_on_rails:bootstrap"
46
58
  invoke "react_on_rails:heroku_deployment" if options.heroku_deployment?
59
+ invoke "react_on_rails:bootstrap" unless options.skip_bootstrap?
47
60
  end
48
61
 
49
- private
50
-
51
62
  # NOTE: other requirements for existing files such as .gitignore or application.
52
63
  # js(.coffee) are not checked by this method, but instead produce warning messages
53
64
  # and allow the build to continue
@@ -1,6 +1,5 @@
1
1
  <h1 class="alert alert-info this-works"><%= options.server_rendering? ? "Server Rendering" : "Client Rendering" %></h1>
2
2
  <%%= react_component("HelloWorldApp",
3
3
  @hello_world_props,
4
- generator_function: false,
5
- prerender: <%= options.server_rendering? %>,
6
- trace: true) %>
4
+ generator_function: true,
5
+ prerender: <%= options.server_rendering? %>) %>
@@ -4,8 +4,8 @@
4
4
  "description": "Built using the react_on_rails generator.",
5
5
  "main": "server.js",
6
6
  "engines": {
7
- "node": "4.2.0",
8
- "npm": "3.3.6"
7
+ "node": "5.0.0",
8
+ "npm": "3.5.0"
9
9
  },
10
10
  "repository": {
11
11
  "type": "git",
@@ -38,58 +38,61 @@
38
38
  "dependencies": {
39
39
  "babel-core": "^5.8.25",
40
40
  "babel-loader": "^5.3.2",
41
- "es5-shim": "^4.1.14",
41
+ "body-parser": "^1.14.1",
42
+ "es5-shim": "^4.3.1",
42
43
  "es6-promise": "^3.0.2",
43
- "expose-loader": "^0.7.0",
44
+ "expose-loader": "^0.7.1",
44
45
  <%- if options.redux? -%>
45
46
  "immutable": "^3.7.5",
46
47
  <%- end -%>
47
- "imports-loader": "^0.6.4",
48
+ "imports-loader": "^0.6.5",
48
49
  "jquery": "^2.1.4",
49
50
  "jquery-ujs": "^1.1.0-1",
50
- <%- if options.redux? -%>
51
- "lodash": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
52
- <%- end -%>
53
51
  "loader-utils": "^0.2.11",
54
52
  <%- if options.redux? -%>
53
+ "lodash": "^3.10.1",
55
54
  "mirror-creator": "0.0.1",
56
55
  <%- end -%>
57
56
  "react": "^0.14.0",
58
- "react-bootstrap": "^0.27.0",
59
- "react-dom": "^0.14.0",
57
+ <%- unless options.skip_bootstrap? -%>
58
+ "react-bootstrap": "^0.28.1",
59
+ <%- end -%>
60
+ "react-dom": "^0.14.3",
60
61
  <%- if options.redux? -%>
61
- "react-redux": "^3.1.0",
62
- "redux": "^3.0.2",
62
+ "react-redux": "^4.0.0",
63
+ "redux": "^3.0.4",
63
64
  "redux-promise": "^0.5.0",
64
65
  "redux-thunk": "^1.0.0",
65
66
  <%- end -%>
66
- "webpack": "^1.12.2"
67
+ "webpack": "^1.12.8"
67
68
  },
68
69
  "devDependencies": {
69
70
  <%- unless options.skip_js_linters? -%>
70
- "babel-eslint": "^4.1.3",
71
+ "babel-eslint": "^4.1.5",
71
72
  <%- end -%>
72
73
  "babel-plugin-react-transform": "^1.1.1",
74
+ <%- unless options.skip_bootstrap? -%>
73
75
  "bootstrap-sass": "^3.3.5",
74
76
  "bootstrap-sass-loader": "^1.0.9",
75
- "css-loader": "^0.19.0",
77
+ <%- end -%>
78
+ "css-loader": "^0.23.0",
76
79
  <%- unless options.skip_js_linters? -%>
77
- "eslint": "^1.6.0",
78
- "eslint-config-airbnb": "0.1.0",
79
- "eslint-plugin-react": "^3.5.1",
80
+ "eslint": "^1.10.1",
81
+ "eslint-config-airbnb": "1.0.0",
82
+ "eslint-plugin-react": "^3.10.0",
80
83
  <%- end -%>
81
84
  "esprima-fb": "^15001.1001.0-dev-harmony-fb",
82
85
  "express": "^4.13.3",
83
86
  "file-loader": "^0.8.4",
84
87
  "jade": "^1.11.0",
85
88
  <%- unless options.skip_js_linters? -%>
86
- "jscs": "^2.3.0",
89
+ "jscs": "^2.6.0",
87
90
  <%- end -%>
88
- "node-sass": "^3.3.3",
91
+ "node-sass": "^3.4.2",
89
92
  "react-transform-hmr": "^1.0.1",
90
- "sass-loader": "^3.0.0",
91
- "style-loader": "^0.12.4",
93
+ "sass-loader": "^3.1.1",
94
+ "style-loader": "^0.13.0",
92
95
  "url-loader": "^0.5.6",
93
- "webpack-dev-server": "^1.12.0"
96
+ "webpack-dev-server": "^1.12.1"
94
97
  }
95
98
  }
@@ -10,11 +10,13 @@ config.entry.app.push(
10
10
 
11
11
  // Webpack dev server
12
12
  'webpack-dev-server/client?http://localhost:4000',
13
- 'webpack/hot/dev-server',
13
+ 'webpack/hot/dev-server'<%- unless options.skip_bootstrap? -%>,
14
14
 
15
15
  // See: https://github.com/shakacode/bootstrap-sass-loader
16
16
  // We're using the bootstrap-sass loader.
17
17
  'bootstrap-sass!./bootstrap-sass.config.js'
18
+ <%- end -%>
19
+
18
20
  );
19
21
 
20
22
  config.output = {
@@ -15,7 +15,9 @@ namespace :assets do
15
15
  desc "Compile assets with webpack"
16
16
  task :webpack do
17
17
  sh "cd client && npm run build:client"
18
+ <%- if options[:server_rendering] -%>
18
19
  sh "cd client && npm run build:server"
20
+ <%- end -%>
19
21
  end
20
22
 
21
23
  task :clobber do
@@ -10,7 +10,7 @@ module.exports = {
10
10
 
11
11
  // the project dir
12
12
  context: __dirname,
13
- entry: ['./app/bundles/HelloWorld/startup/serverGlobals'],
13
+ entry: ['./app/bundles/HelloWorld/startup/serverGlobals', 'react', 'react-dom/server'],
14
14
  output: {
15
15
  filename: 'server-bundle.js',
16
16
  path: '../app/assets/javascripts/generated',
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
@@ -0,0 +1,25 @@
1
+ require_relative "../rails_helper"
2
+
3
+ feature "Hello World", js: true do
4
+ scenario "the hello world example works" do
5
+ visit "/hello_world"
6
+ expect(heading).to have_text("Rendering")
7
+ expect(message).to have_text("Stranger")
8
+ name_input.set("John Doe")
9
+ expect(message).to have_text("John Doe")
10
+ end
11
+ end
12
+
13
+ private
14
+
15
+ def name_input
16
+ page.first("input")
17
+ end
18
+
19
+ def message
20
+ page.first(:css, "h3")
21
+ end
22
+
23
+ def heading
24
+ page.first(:css, "h1")
25
+ end
@@ -0,0 +1,57 @@
1
+ # This file is copied to spec/ when you run "rails generate rspec:install"
2
+ ENV["RAILS_ENV"] ||= "test"
3
+ require_relative "../config/environment"
4
+ require_relative "simplecov_helper"
5
+ # Prevent database truncation if the environment is production
6
+ abort("The Rails environment is running in production mode!") if Rails.env.production?
7
+ require_relative "spec_helper"
8
+
9
+ # Add additional requires below this line. Rails is not loaded until this point!
10
+
11
+ require "rspec/rails"
12
+ require "capybara/rspec"
13
+ require "capybara/rails"
14
+
15
+ # Requires supporting ruby files with custom matchers and macros, etc, in
16
+ # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
17
+ # run as spec files by default. This means that files in spec/support that end
18
+ # in _spec.rb will both be required and run as specs, causing the specs to be
19
+ # run twice. It is recommended that you do not name files matching this glob to
20
+ # end with _spec.rb. You can configure this pattern with the --pattern
21
+ # option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
22
+ #
23
+ # The following line is provided for convenience purposes. It has the downside
24
+ # of increasing the boot-up time by auto-requiring all files in the support
25
+ # directory. Alternatively, in the individual `*_spec.rb` files, manually
26
+ # require only the support files necessary.
27
+ #
28
+ # Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
29
+
30
+ # Checks for pending migrations before tests are run.
31
+ # If you are not using ActiveRecord, you can remove this line.
32
+ # ActiveRecord::Migration.maintain_test_schema!
33
+
34
+ RSpec.configure do |config|
35
+ # Remove this line if you"re not using ActiveRecord or ActiveRecord fixtures
36
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
37
+
38
+ # If you"re not using ActiveRecord, or you"d prefer not to run each of your
39
+ # examples within a transaction, remove the following line or assign false
40
+ # instead of true.
41
+ config.use_transactional_fixtures = true
42
+
43
+ # RSpec Rails can automatically mix in different behaviours to your tests
44
+ # based on their file location, for example enabling you to call `get` and
45
+ # `post` in specs under `spec/controllers`.
46
+ #
47
+ # You can disable this behaviour by removing the line below, and instead
48
+ # explicitly tag your specs with their type, e.g.:
49
+ #
50
+ # RSpec.describe UsersController, :type => :controller do
51
+ # # ...
52
+ # end
53
+ #
54
+ # The different available types are documented in the features, such as in
55
+ # https://relishapp.com/rspec/rspec-rails/docs
56
+ config.infer_spec_type_from_file_location!
57
+ end