2017-08-14 13:08:09 -04:00
# frozen_string_literal: true
2011-05-06 18:11:13 -04:00
#
# Tests, setup, and teardown common to the application and plugin generator suites.
#
2010-10-20 18:55:08 -04:00
module SharedGeneratorTests
def setup
Rails . application = TestApp :: Application
super
2016-08-06 13:16:09 -04:00
Rails :: Generators :: AppGenerator . instance_variable_set ( " @desc " , nil )
2010-10-20 18:55:08 -04:00
Kernel :: silence_warnings do
Thor :: Base . shell . send ( :attr_accessor , :always_force )
@shell = Thor :: Base . shell . new
@shell . send ( :always_force = , true )
end
end
def teardown
super
2016-08-06 13:16:09 -04:00
Rails :: Generators :: AppGenerator . instance_variable_set ( " @desc " , nil )
2010-10-20 18:55:08 -04:00
Rails . application = TestApp :: Application . instance
end
2017-08-13 16:12:07 -04:00
def application_path
destination_root
end
2010-10-20 18:55:08 -04:00
def test_skeleton_is_created
run_generator
2011-05-12 18:43:43 -04:00
default_files . each { | path | assert_file path }
end
2010-10-20 18:55:08 -04:00
def test_plugin_new_generate_pretend
run_generator [ " testapp " , " --pretend " ]
2016-10-28 23:05:58 -04:00
default_files . each { | path | assert_no_file File . join ( " testapp " , path ) }
2010-10-20 18:55:08 -04:00
end
2010-11-02 09:23:45 -04:00
def test_invalid_database_option_raises_an_error
2016-08-16 03:30:11 -04:00
content = capture ( :stderr ) { run_generator ( [ destination_root , " -d " , " unknown " ] ) }
2011-03-12 19:01:12 -05:00
assert_match ( / Invalid value for \ - \ -database option / , content )
2010-11-02 09:23:45 -04:00
end
2015-01-29 15:44:26 -05:00
def test_test_files_are_skipped_if_required
2015-01-27 17:59:48 -05:00
run_generator [ destination_root , " --skip-test " ]
2010-11-02 09:52:08 -04:00
assert_no_file " test "
end
2010-10-20 18:55:08 -04:00
def test_name_collision_raises_an_error
reserved_words = %w[ application destroy plugin runner test ]
reserved_words . each do | reserved |
2016-08-16 03:30:11 -04:00
content = capture ( :stderr ) { run_generator [ File . join ( destination_root , reserved ) ] }
2017-05-06 15:08:58 -04:00
assert_match ( / Invalid \ w+ name #{ reserved } \ . Please give a name which does not match one of the reserved rails words: application, destroy, plugin, runner, test \ n / , content )
2010-10-20 18:55:08 -04:00
end
end
def test_name_raises_an_error_if_name_already_used_constant
%w{ String Hash Class Module Set Symbol } . each do | ruby_class |
2016-08-16 03:30:11 -04:00
content = capture ( :stderr ) { run_generator [ File . join ( destination_root , ruby_class ) ] }
2017-05-06 15:08:58 -04:00
assert_match ( / Invalid \ w+ name #{ ruby_class } , constant #{ ruby_class } is already in use \ . Please choose another \ w+ name \ . \ n / , content )
2010-10-20 18:55:08 -04:00
end
end
def test_shebang_is_added_to_rails_file
2017-11-08 16:39:35 -05:00
run_generator [ destination_root , " --ruby " , " foo/bar/baz " , " --full " ]
2013-01-06 18:13:47 -05:00
assert_file " bin/rails " , / # !foo \/ bar \/ baz /
2010-10-20 18:55:08 -04:00
end
def test_shebang_when_is_the_same_as_default_use_env
2011-05-27 07:44:10 -04:00
run_generator [ destination_root , " --ruby " , Thor :: Util . ruby_command , " --full " ]
2013-01-06 18:13:47 -05:00
assert_file " bin/rails " , / # ! \/ usr \/ bin \/ env /
2010-10-20 18:55:08 -04:00
end
def test_template_raises_an_error_with_invalid_path
2014-04-27 12:19:29 -04:00
quietly do
2016-08-16 03:30:11 -04:00
content = capture ( :stderr ) { run_generator ( [ destination_root , " -m " , " non/existent/path " ] ) }
2014-04-27 12:19:29 -04:00
assert_match ( / The template \ [.* \ ] could not be loaded / , content )
assert_match ( / non \/ existent \/ path / , content )
end
2010-10-20 18:55:08 -04:00
end
2010-11-27 05:40:42 -05:00
def test_template_is_executed_when_supplied_an_https_path
2013-02-18 09:57:37 -05:00
path = " https://gist.github.com/josevalim/103208/raw/ "
2017-07-22 08:45:53 -04:00
template = %{ say "It works!" } . dup
2010-11-27 05:40:42 -05:00
template . instance_eval " def read; self; end " # Make the string respond to read
2015-08-20 23:27:37 -04:00
check_open = - > * args do
2016-08-06 13:16:09 -04:00
assert_equal [ path , " Accept " = > " application/x-thor-template " ] , args
2015-08-20 23:27:37 -04:00
template
end
generator ( [ destination_root ] , template : path ) . stub ( :open , check_open , template ) do
quietly { assert_match ( / It works! / , capture ( :stdout ) { generator . invoke_all } ) }
end
2010-10-20 18:55:08 -04:00
end
2011-05-12 18:43:43 -04:00
def test_skip_gemfile
2015-08-20 23:27:37 -04:00
assert_not_called ( generator ( [ destination_root ] , skip_gemfile : true ) , :bundle_command ) do
quietly { generator . invoke_all }
2016-08-06 13:16:09 -04:00
assert_no_file " Gemfile "
2015-08-20 23:27:37 -04:00
end
2011-05-13 20:36:29 -04:00
end
2012-09-12 21:15:38 -04:00
def test_skip_git
2016-08-06 13:16:09 -04:00
run_generator [ destination_root , " --skip-git " , " --full " ]
assert_no_file ( " .gitignore " )
2017-01-10 08:58:28 -05:00
assert_no_directory ( " .git " )
2012-09-12 21:15:38 -04:00
end
def test_skip_keeps
2016-08-06 13:16:09 -04:00
run_generator [ destination_root , " --skip-keeps " , " --full " ]
2015-05-22 08:24:48 -04:00
2016-08-06 13:16:09 -04:00
assert_file " .gitignore " do | content |
2015-05-22 08:24:48 -04:00
assert_no_match ( / \ .keep / , content )
end
2016-08-06 13:16:09 -04:00
assert_no_file ( " app/models/concerns/.keep " )
2012-09-12 21:15:38 -04:00
end
2017-08-13 16:12:07 -04:00
2017-08-15 12:01:13 -04:00
def test_default_frameworks_are_required_when_others_are_removed
2017-08-07 00:31:14 -04:00
run_generator [
destination_root ,
" --skip-active-record " ,
" --skip-active-storage " ,
" --skip-action-mailer " ,
" --skip-action-cable " ,
" --skip-sprockets "
]
assert_file " #{ application_path } /config/application.rb " , / ^require \ s+["']rails["'] /
assert_file " #{ application_path } /config/application.rb " , / ^require \ s+["']active_model \/ railtie["'] /
assert_file " #{ application_path } /config/application.rb " , / ^require \ s+["']active_job \/ railtie["'] /
assert_file " #{ application_path } /config/application.rb " , / ^ # require \ s+["']active_record \/ railtie["'] /
assert_file " #{ application_path } /config/application.rb " , / ^ # require \ s+["']active_storage \/ engine["'] /
assert_file " #{ application_path } /config/application.rb " , / ^require \ s+["']action_controller \/ railtie["'] /
assert_file " #{ application_path } /config/application.rb " , / ^ # require \ s+["']action_mailer \/ railtie["'] /
assert_file " #{ application_path } /config/application.rb " , / ^require \ s+["']action_view \/ railtie["'] /
assert_file " #{ application_path } /config/application.rb " , / ^ # require \ s+["']action_cable \/ engine["'] /
assert_file " #{ application_path } /config/application.rb " , / ^ # require \ s+["']sprockets \/ railtie["'] /
assert_file " #{ application_path } /config/application.rb " , / ^require \ s+["']rails \/ test_unit \/ railtie["'] /
2017-08-15 12:01:13 -04:00
end
def test_generator_without_skips
run_generator
assert_file " #{ application_path } /config/application.rb " , / \ s+require \ s+["']rails \/ all["'] /
assert_file " #{ application_path } /config/environments/development.rb " do | content |
assert_match ( / config \ .action_mailer \ .raise_delivery_errors = false / , content )
end
assert_file " #{ application_path } /config/environments/test.rb " do | content |
assert_match ( / config \ .action_mailer \ .delivery_method = :test / , content )
end
assert_file " #{ application_path } /config/environments/production.rb " do | content |
assert_match ( / # config \ .action_mailer \ .raise_delivery_errors = false / , content )
Add credentials using a generic EncryptedConfiguration class (#30067)
* WIP: Add credentials using a generic EncryptedConfiguration class
This is sketch code so far.
* Flesh out EncryptedConfiguration and test it
* Better name
* Add command and generator for credentials
* Use the Pathnames
* Extract EncryptedFile from EncryptedConfiguration and add serializers
* Test EncryptedFile
* Extract serializer validation
* Stress the point about losing comments
* Allow encrypted configuration to be read without parsing for display
* Use credentials by default and base them on the master key
* Derive secret_key_base in test/dev, source it from credentials in other envs
And document the usage.
* Document the new credentials setup
* Stop generating the secrets.yml file now that we have credentials
* Document what we should have instead
Still need to make it happen, tho.
* [ci skip] Keep wording to `key base`; prefer defaults.
Usually we say we change defaults, not "spec" out a release.
Can't use backticks in our sdoc generated documentation either.
* Abstract away OpenSSL; prefer MessageEncryptor.
* Spare needless new when raising.
* Encrypted file test shouldn't depend on subclass.
* [ci skip] Some woordings.
* Ditch serializer future coding.
* I said flip it. Flip it good.
* [ci skip] Move require_master_key to the real production.rb.
* Add require_master_key to abort the boot process.
In case the master key is required in a certain environment
we should inspect that the key is there and abort if it isn't.
* Print missing key message and exit immediately.
Spares us a lengthy backtrace and prevents further execution.
I've verified the behavior in a test app, but couldn't figure the
test out as loading the app just exits immediately with:
```
/Users/kasperhansen/Documents/code/rails/activesupport/lib/active_support/testing/isolation.rb:23:in `load': marshal data too short (ArgumentError)
from /Users/kasperhansen/Documents/code/rails/activesupport/lib/active_support/testing/isolation.rb:23:in `run'
from /Users/kasperhansen/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/minitest-5.10.2/lib/minitest.rb:830:in `run_one_method'
from /Users/kasperhansen/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/minitest-5.10.2/lib/minitest/parallel.rb:32:in `block (2 levels) in start'
```
It's likely we need to capture and prevent the exit somehow.
Kernel.stub(:exit) didn't work. Leaving it for tomorrow.
* Fix require_master_key config test.
Loading the app would trigger the `exit 1` per require_master_key's
semantics, which then aborted the test.
Fork and wait for the child process to finish, then inspect the
exit status.
Also check we aborted because of a missing master key, so something
else didn't just abort the boot.
Much <3 to @tenderlove for the tip.
* Support reading/writing configs via methods.
* Skip needless deep symbolizing.
* Remove save; test config reader elsewhere.
* Move secret_key_base check to when we're reading it.
Otherwise we'll abort too soon since we don't assign the secret_key_base
to secrets anymore.
* Add missing string literal comments; require unneeded yaml require.
* ya ya ya, rubocop.
* Add master_key/credentials after bundle.
Then we can reuse the existing message on `rails new bc4`.
It'll look like:
```
Using web-console 3.5.1 from https://github.com/rails/web-console.git (at master@ce985eb)
Using rails 5.2.0.alpha from source at `/Users/kasperhansen/Documents/code/rails`
Using sass-rails 5.0.6
Bundle complete! 16 Gemfile dependencies, 72 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
Adding config/master.key to store the master encryption key: 97070158c44b4675b876373a6bc9d5a0
Save this in a password manager your team can access.
If you lose the key, no one, including you, can access anything encrypted with it.
create config/master.key
```
And that'll be executed even if `--skip-bundle` was passed.
* Ensure test app has secret_key_base.
* Assign secret_key_base to app or omit.
* Merge noise
* Split options for dynamic delegation into its own method and use deep symbols to make it work
* Update error to point to credentials instead
* Appease Rubocop
* Validate secret_key_base when reading it.
Instead of relying on the validation in key_generator move that into
secret_key_base itself.
* Fix generator and secrets test.
Manually add config.read_encrypted_secrets since it's not there by default
anymore.
Move mentions of config/secrets.yml to config/credentials.yml.enc.
* Remove files I have no idea how they got here.
* [ci skip] swap secrets for credentials.
* [ci skip] And now, changelogs are coming.
2017-09-11 14:21:20 -04:00
assert_match ( / ^ # config \ .require_master_key = true / , content )
2017-08-15 12:01:13 -04:00
end
end
def test_gitignore_when_sqlite3
run_generator
assert_file " .gitignore " do | content |
assert_match ( / sqlite3 / , content )
end
end
def test_gitignore_when_non_sqlite3_db
run_generator ( [ destination_root , " -d " , " mysql " ] )
assert_file " .gitignore " do | content |
assert_no_match ( / sqlite /i , content )
end
end
def test_generator_if_skip_active_record_is_given
run_generator [ destination_root , " --skip-active-record " ]
assert_no_directory " #{ application_path } /db/ "
assert_no_file " #{ application_path } /config/database.yml "
assert_no_file " #{ application_path } /app/models/application_record.rb "
assert_file " #{ application_path } /config/application.rb " , / # \ s+require \ s+["']active_record \/ railtie["'] /
assert_file " test/test_helper.rb " do | helper_content |
assert_no_match ( / fixtures :all / , helper_content )
end
assert_file " #{ application_path } /bin/setup " do | setup_content |
assert_no_match ( / db:setup / , setup_content )
end
assert_file " #{ application_path } /bin/update " do | update_content |
assert_no_match ( / db:migrate / , update_content )
end
assert_file " .gitignore " do | content |
assert_no_match ( / sqlite /i , content )
end
end
2017-08-06 16:41:31 -04:00
def test_generator_for_active_storage
run_generator
assert_file " #{ application_path } /app/assets/javascripts/application.js " do | content |
assert_match ( / ^ \/ \/ = require activestorage / , content )
end
assert_file " #{ application_path } /config/environments/development.rb " do | content |
assert_match ( / config \ .active_storage / , content )
end
assert_file " #{ application_path } /config/environments/production.rb " do | content |
assert_match ( / config \ .active_storage / , content )
end
assert_file " #{ application_path } /config/environments/test.rb " do | content |
assert_match ( / config \ .active_storage / , content )
end
assert_file " #{ application_path } /config/storage.yml "
assert_directory " #{ application_path } /storage "
assert_directory " #{ application_path } /tmp/storage "
assert_file " .gitignore " do | content |
assert_match ( / \/ storage \/ / , content )
end
end
def test_generator_if_skip_active_storage_is_given
run_generator [ destination_root , " --skip-active-storage " ]
assert_file " #{ application_path } /config/application.rb " , / # \ s+require \ s+["']active_storage \/ engine["'] /
assert_file " #{ application_path } /app/assets/javascripts/application.js " do | content |
assert_no_match ( / ^ \/ \/ = require activestorage / , content )
end
assert_file " #{ application_path } /config/environments/development.rb " do | content |
assert_no_match ( / config \ .active_storage / , content )
end
assert_file " #{ application_path } /config/environments/production.rb " do | content |
assert_no_match ( / config \ .active_storage / , content )
end
assert_file " #{ application_path } /config/environments/test.rb " do | content |
assert_no_match ( / config \ .active_storage / , content )
end
assert_no_file " #{ application_path } /config/storage.yml "
assert_no_directory " #{ application_path } /db/migrate "
assert_no_directory " #{ application_path } /storage "
assert_no_directory " #{ application_path } /tmp/storage "
assert_file " .gitignore " do | content |
assert_no_match ( / \/ storage \/ / , content )
end
end
def test_generator_does_not_generate_active_storage_contents_if_skip_active_record_is_given
run_generator [ destination_root , " --skip-active-record " ]
assert_file " #{ application_path } /config/application.rb " , / # \ s+require \ s+["']active_storage \/ engine["'] /
assert_file " #{ application_path } /app/assets/javascripts/application.js " do | content |
assert_no_match ( / ^ \/ \/ = require activestorage / , content )
end
assert_file " #{ application_path } /config/environments/development.rb " do | content |
assert_no_match ( / config \ .active_storage / , content )
end
assert_file " #{ application_path } /config/environments/production.rb " do | content |
assert_no_match ( / config \ .active_storage / , content )
end
assert_file " #{ application_path } /config/environments/test.rb " do | content |
assert_no_match ( / config \ .active_storage / , content )
end
assert_no_file " #{ application_path } /config/storage.yml "
assert_no_directory " #{ application_path } /db/migrate "
assert_no_directory " #{ application_path } /storage "
assert_no_directory " #{ application_path } /tmp/storage "
assert_file " .gitignore " do | content |
assert_no_match ( / \/ storage \/ / , content )
end
end
2017-08-15 12:01:13 -04:00
def test_generator_if_skip_action_mailer_is_given
run_generator [ destination_root , " --skip-action-mailer " ]
assert_file " #{ application_path } /config/application.rb " , / # \ s+require \ s+["']action_mailer \/ railtie["'] /
assert_file " #{ application_path } /config/environments/development.rb " do | content |
assert_no_match ( / config \ .action_mailer / , content )
end
assert_file " #{ application_path } /config/environments/test.rb " do | content |
assert_no_match ( / config \ .action_mailer / , content )
end
assert_file " #{ application_path } /config/environments/production.rb " do | content |
assert_no_match ( / config \ .action_mailer / , content )
end
assert_no_directory " #{ application_path } /app/mailers "
assert_no_directory " #{ application_path } /test/mailers "
end
def test_generator_if_skip_action_cable_is_given
run_generator [ destination_root , " --skip-action-cable " ]
assert_file " #{ application_path } /config/application.rb " , / # \ s+require \ s+["']action_cable \/ engine["'] /
assert_no_file " #{ application_path } /config/cable.yml "
assert_no_file " #{ application_path } /app/assets/javascripts/cable.js "
assert_no_directory " #{ application_path } /app/assets/javascripts/channels "
assert_no_directory " #{ application_path } /app/channels "
assert_file " Gemfile " do | content |
assert_no_match ( / redis / , content )
end
end
def test_generator_if_skip_sprockets_is_given
run_generator [ destination_root , " --skip-sprockets " ]
assert_no_file " #{ application_path } /config/initializers/assets.rb "
assert_file " #{ application_path } /config/application.rb " , / # \ s+require \ s+["']sprockets \/ railtie["'] /
assert_file " Gemfile " do | content |
assert_no_match ( / sass-rails / , content )
assert_no_match ( / uglifier / , content )
assert_no_match ( / coffee-rails / , content )
end
assert_file " #{ application_path } /config/environments/development.rb " do | content |
assert_no_match ( / config \ .assets \ .debug / , content )
end
assert_file " #{ application_path } /config/environments/production.rb " do | content |
assert_no_match ( / config \ .assets \ .digest / , content )
assert_no_match ( / config \ .assets \ .js_compressor / , content )
assert_no_match ( / config \ .assets \ .css_compressor / , content )
assert_no_match ( / config \ .assets \ .compile / , content )
end
end
2017-08-13 16:12:07 -04:00
def test_generator_for_yarn
run_generator
assert_file " #{ application_path } /package.json " , / dependencies /
assert_file " #{ application_path } /config/initializers/assets.rb " , / node_modules /
assert_file " .gitignore " do | content |
assert_match ( / node_modules / , content )
assert_match ( / yarn-error \ .log / , content )
end
end
def test_generator_for_yarn_skipped
run_generator ( [ destination_root , " --skip-yarn " ] )
assert_no_file " #{ application_path } /package.json "
assert_no_file " #{ application_path } /bin/yarn "
assert_file " #{ application_path } /config/initializers/assets.rb " do | content |
assert_no_match ( / node_modules / , content )
end
assert_file " .gitignore " do | content |
assert_no_match ( / node_modules / , content )
assert_no_match ( / yarn-error \ .log / , content )
end
end
2010-10-20 18:55:08 -04:00
end