Skip to content

Commit 4a49ffe

Browse files
committed
Basic generator specs
1 parent c13eefb commit 4a49ffe

File tree

6 files changed

+263
-18
lines changed

6 files changed

+263
-18
lines changed

lib/generators/sorcery/helpers.rb

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@ module Generators
33
module Helpers
44
private
55

6-
def file_path
7-
model_name.underscore
6+
def initializer_path
7+
File.join(initializers_path, 'sorcery.rb')
8+
end
9+
10+
def initializers_path
11+
File.join('config', 'initializers')
812
end
913

1014
def migration_class_name
@@ -15,6 +19,14 @@ def migration_class_name
1519
end
1620
end
1721

22+
def migration_path(submodule)
23+
File.join(migrations_path, "sorcery_#{submodule}.rb")
24+
end
25+
26+
def migrations_path
27+
File.join('db', 'migrate')
28+
end
29+
1830
# Either return the model passed in a classified form or return the default "User".
1931
def model_class_name
2032
options[:model] ? options[:model].classify : 'User'
@@ -40,7 +52,11 @@ def model_name
4052
end
4153

4254
def model_path
43-
@model_path ||= File.join('app', 'models', "#{file_path}.rb")
55+
File.join(models_path, "#{model_name.underscore}.rb")
56+
end
57+
58+
def models_path
59+
File.join('app', 'models')
4460
end
4561

4662
def model_superclass_name
@@ -59,10 +75,6 @@ def only_submodules?
5975
options[:migrations] || options[:only_submodules]
6076
end
6177

62-
def sorcery_config_path
63-
'config/initializers/sorcery.rb'
64-
end
65-
6678
def tableized_model_class
6779
model_class_name.gsub(/::/, '').tableize
6880
end

lib/generators/sorcery/install_generator.rb

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,24 +47,21 @@ def check_available_submodules
4747
end
4848
end
4949

50-
# Copy the initializer file to config/initializers folder.
51-
def copy_initializer_file
52-
template 'initializer.rb', sorcery_config_path unless only_submodules?
53-
end
50+
# Copy the initializer file to config/initializers folder, and add the submodules if necessary.
51+
def install_initializer
52+
template 'initializer.rb', initializer_path unless only_submodules?
5453

55-
def configure_initializer_file
56-
# Add submodules to the initializer file.
5754
return unless submodules
5855

5956
submodule_names = submodules.collect { |submodule| ':' + submodule }
6057

61-
gsub_file sorcery_config_path, /submodules = \[.*\]/ do |str|
58+
gsub_file initializer_path, /submodules = \[.*\]/ do |str|
6259
current_submodule_names = (str =~ /\[(.*)\]/ ? Regexp.last_match(1) : '').delete(' ').split(',')
6360
"submodules = [#{(current_submodule_names | submodule_names).join(', ')}]"
6461
end
6562
end
6663

67-
def configure_model
64+
def install_model
6865
# Generate the model and add 'authenticates_with_sorcery!' unless you passed --only-submodules
6966
return if only_submodules?
7067

@@ -74,17 +71,17 @@ def configure_model
7471
end
7572

7673
# Copy the migrations files to db/migrate folder
77-
def copy_migration_files
74+
def install_migrations
7875
# Copy core migration file in all cases except when you pass --only-submodules.
7976
return unless defined?(ActiveRecord)
8077

81-
migration_template 'migration/core.rb', 'db/migrate/sorcery_core.rb', migration_class_name: migration_class_name unless only_submodules?
78+
migration_template 'migration/core.rb', migration_path(:core), migration_class_name: migration_class_name unless only_submodules?
8279

8380
return unless submodules
8481

8582
submodules.each do |submodule|
8683
unless %w[http_basic_auth session_timeout core].include?(submodule)
87-
migration_template "migration/#{submodule}.rb", "db/migrate/sorcery_#{submodule}.rb", migration_class_name: migration_class_name
84+
migration_template "migration/#{submodule}.rb", migration_path(submodule), migration_class_name: migration_class_name
8885
end
8986
end
9087
end
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
require 'spec_helper'
2+
require 'support/generator_helper'
3+
4+
require 'generators/sorcery/install_generator'
5+
6+
describe 'install generator' do
7+
include GeneratorHelper
8+
9+
class TestInstallGenerator < Sorcery::Generators::InstallGenerator
10+
source_root File.expand_path('../../lib/generators/sorcery/templates', __dir__)
11+
12+
def self.next_migration_number(dirname)
13+
current_migration_number(dirname) + 1
14+
end
15+
end
16+
17+
tests TestInstallGenerator
18+
19+
context 'given deprecated --migrations option' do
20+
let(:installer) do
21+
generator(options: { migrations: true })
22+
end
23+
24+
it 'shows warning' do
25+
expect(installer).to receive(:warn).with(/\[DEPRECATED\] `--migrations` option is deprecated/)
26+
installer.check_deprecated_options
27+
end
28+
end
29+
30+
context 'given invalid submodule' do
31+
it 'raises error' do
32+
expect {
33+
generator('invalid_submodule').check_available_submodules
34+
}.to raise_error(ArgumentError).with_message(/invalid_submodule is not a Sorcery submodule/)
35+
end
36+
end
37+
38+
describe 'initializer' do
39+
describe 'installation' do
40+
let(:installation) { invoke!(:install_initializer) }
41+
42+
it 'creates initializer' do
43+
expect(installation).to match(/create config\/initializers\/sorcery.rb/)
44+
end
45+
end
46+
47+
describe 'configuration' do
48+
context 'given submodule(s)' do
49+
let(:initializer_contents) do
50+
File.read(initializer_path)
51+
end
52+
53+
before do
54+
invoke!(:install_initializer, 'activity_logging')
55+
end
56+
57+
it 'adds submodule(s) to initializer' do
58+
expect(initializer_contents).to match(/Rails\.application\.config\.sorcery\.submodules = \[:activity_logging\]/)
59+
end
60+
end
61+
end
62+
63+
describe 'uninstallation' do
64+
let(:uninstallation) { revoke!(:install_initializer) }
65+
66+
before do
67+
invoke!(:install_initializer)
68+
end
69+
70+
it 'removes initializer' do
71+
expect(uninstallation).to match(/remove config\/initializers\/sorcery.rb/)
72+
end
73+
end
74+
end
75+
76+
describe 'model' do
77+
describe 'installation' do
78+
let(:installation) { invoke!(:install_model) }
79+
80+
it 'skips migration' do
81+
expect(installation).to match(/generate model User \-\-skip\-migration/)
82+
end
83+
84+
it 'creates model' do
85+
expect(installation).to match(/create app\/models\/user\.rb/)
86+
end
87+
end
88+
89+
describe 'configuration' do
90+
let(:model_contents) do
91+
File.read(model_path(:user))
92+
end
93+
94+
before do
95+
invoke!(:install_model)
96+
end
97+
98+
it 'adds `authenticates_with_sorcery!`' do
99+
expect(model_contents).to match(/authenticates_with_sorcery!/)
100+
end
101+
end
102+
103+
describe 'uninstallation' do
104+
let(:uninstallation) { revoke!(:install_model) }
105+
106+
before do
107+
invoke!(:install_model)
108+
end
109+
110+
it 'removes `authenticates_with_sorcery!`' do
111+
expect(uninstallation).to match(/subtract app\/models\/user.rb/)
112+
end
113+
end
114+
end
115+
116+
describe 'migrations' do
117+
describe 'installation' do
118+
let(:installation) { invoke!(:install_migrations, 'activity_logging', options: { only_submodules: true }) }
119+
120+
it 'creates migration' do
121+
expect(installation).to match(/create db\/migrate\/1_sorcery_activity_logging.rb/)
122+
end
123+
end
124+
125+
describe 'uninstallation' do
126+
let(:uninstallation) { revoke!(:install_migrations, 'activity_logging', options: { only_submodules: true }) }
127+
128+
it 'removes migration' do
129+
expect(uninstallation).to match(/remove db\/migrate\/1_sorcery_activity_logging.rb/)
130+
end
131+
end
132+
end
133+
end

spec/rails_app/bin/rails

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/usr/bin/env ruby
2+
3+
# Really, this should come from spec_helper.rb somehow -- but for some reason, doesn't work
4+
# when running generators... this is why it's added here. Hopefully someone a little wiser
5+
# than I can fix this.
6+
#
7+
SORCERY_ORM = :active_record
8+
9+
APP_PATH = File.expand_path('../config/application', __dir__)
10+
require_relative '../config/boot'
11+
require 'rails/commands'

spec/spec_helper.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
# SimpleCov.root File.join(File.dirname(__FILE__), '..', 'lib')
1010
# SimpleCov.start
1111
require 'rails/all'
12+
require 'rails-controller-testing'
1213
require 'rspec/rails'
1314
require 'timecop'
1415
require 'byebug'

spec/support/generator_helper.rb

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
require 'active_support/concern'
2+
require 'active_support/testing/stream'
3+
require 'rails/generators'
4+
5+
module GeneratorHelper
6+
extend ActiveSupport::Concern
7+
include ActiveSupport::Testing::Stream
8+
include FileUtils
9+
10+
included do |base|
11+
class_attribute :destination_root, default: File.expand_path('../rails_app', __dir__)
12+
class_attribute :generator_class
13+
14+
base.teardown :remove_installation!
15+
end
16+
17+
module ClassMethods
18+
def tests(klass)
19+
self.generator_class = klass
20+
end
21+
22+
def destination(path)
23+
self.destination_root = path
24+
end
25+
end
26+
27+
# Instantiate the generator.
28+
def generator(*args, options: {}, config: {})
29+
generator_class.new(args, options, config.reverse_merge(destination_root: destination_root))
30+
end
31+
32+
# Invoke a specific action
33+
def invoke!(action, *args, options: {}, config: {})
34+
gen = generator(*args, options: options, config: config.reverse_merge(behavior: :invoke))
35+
36+
capture(:stdout) do
37+
gen.invoke(action)
38+
end
39+
end
40+
41+
# Revoke a specific action
42+
def revoke!(action, *args, options: {}, config: {})
43+
gen = generator(*args, options: options, config: config.reverse_merge(behavior: :revoke))
44+
45+
capture(:stdout) do
46+
gen.invoke(action)
47+
end
48+
end
49+
50+
def initializer_path
51+
@initializer_path ||= File.join(destination_root, 'config', 'initializers', 'sorcery.rb')
52+
end
53+
54+
def migrations_path
55+
@migrations_path ||= File.join(destination_root, 'db', 'migrate')
56+
end
57+
58+
# def migration_path(migration)
59+
# @migration_path ||= {}
60+
# @migration_path[migration.to_s] ||= Dir.glob("#{migrations_path}/[0-9]*_*.rb")
61+
# .grep(/\d+_#{migration}.rb$/)
62+
# .first
63+
# end
64+
65+
def model_path(model)
66+
@model_path ||= {}
67+
@model_path[model.to_s] ||= File.join(destination_root, 'app', 'models', "#{model}.rb")
68+
end
69+
70+
private
71+
72+
def remove_installation!
73+
# Remove any generated initializers, models, migrations files
74+
files = [initializer_path]
75+
files += Dir.glob(File.join(destination_root, 'app', 'models', '*.rb'))
76+
files += Dir.glob(File.join(destination_root, 'db', 'migrate', '*.rb'))
77+
78+
files.each do |file|
79+
rm_f(file) if File.exists?(file)
80+
end
81+
82+
# Recursively remove full directories
83+
dirs = [
84+
File.join(destination_root, 'test')
85+
]
86+
87+
dirs.each do |dir|
88+
rm_rf(dir) if Dir.exists?(dir)
89+
end
90+
end
91+
end

0 commit comments

Comments
 (0)