shoestrap 1.0.0.pre1 → 1.0.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +1 -2
  4. data/CHANGELOG.md +12 -1
  5. data/Guardfile +1 -0
  6. data/Rakefile +1 -1
  7. data/circle.yml +3 -0
  8. data/features/command_wrapper_helper.rb +94 -0
  9. data/features/custom_matcher.rb +23 -0
  10. data/features/features_helper.rb +76 -29
  11. data/features/postgres_helper.rb +69 -0
  12. data/features/shoestrap/commands/new_command_spec.rb +234 -0
  13. data/features/shoestrap/generators/{bdd_generator_feature.rb → bdd_generator_spec.rb} +7 -5
  14. data/features/shoestrap/generators/bootstrap_generator_spec.rb +21 -0
  15. data/features/shoestrap/generators/cms_generator_spec.rb +149 -0
  16. data/features/shoestrap/generators/{coffee_files_generator_feature.rb → coffee_files_generator_spec.rb} +0 -0
  17. data/features/shoestrap/generators/{foundation_generator_feature.rb → foundation_generator_spec.rb} +7 -0
  18. data/features/shoestrap/generators/kuhsaft_generator_spec.rb +57 -0
  19. data/features/shoestrap/generators/{smacss_files_generator_feature.rb → smacss_files_generator_spec.rb} +0 -0
  20. data/features/shoestrap/generators/view_files_generator_spec.rb +20 -0
  21. data/lib/generators/shoestrap/base_generator.rb +41 -0
  22. data/lib/generators/shoestrap/bdd_generator.rb +1 -5
  23. data/lib/generators/shoestrap/bootstrap_generator.rb +3 -0
  24. data/lib/generators/shoestrap/cms_generator.rb +59 -0
  25. data/lib/generators/shoestrap/coffee_files_generator.rb +1 -5
  26. data/lib/generators/shoestrap/foundation_generator.rb +5 -5
  27. data/lib/generators/shoestrap/kuhsaft_generator.rb +6 -5
  28. data/lib/generators/shoestrap/mailcatcher_generator.rb +12 -0
  29. data/lib/generators/shoestrap/simple_navigation_generator.rb +14 -0
  30. data/lib/generators/shoestrap/smacss_file_generator.rb +1 -5
  31. data/lib/generators/shoestrap/view_files_generator.rb +11 -0
  32. data/lib/shoestrap/application_generator.rb +14 -38
  33. data/lib/shoestrap/shell.rb +1 -0
  34. data/lib/shoestrap/version.rb +1 -1
  35. data/shoestrap.gemspec +12 -3
  36. data/spec/shoestrap/application_generator_spec.rb +37 -20
  37. data/spec/spec_helper.rb +1 -1
  38. data/templates/application_generator/_typekit.html.haml +4 -0
  39. data/templates/application_generator/application.html.haml +10 -10
  40. data/templates/application_generator/application_template.rb +19 -3
  41. data/templates/bdd_generator/active_record_spec_helper.rb +1 -1
  42. data/templates/cms_generator/base_controller.rb +2 -0
  43. data/templates/{coffee_generator → coffee_files_generator}/application.js.coffee +0 -0
  44. data/templates/simple_navigation_generator/navigation.rb +76 -0
  45. data/templates/{smacss_generator → smacss_files_generator}/application.css.sass +0 -0
  46. metadata +39 -21
  47. data/features/shoestrap/commands/new_command_feature.rb +0 -191
  48. data/features/shoestrap/generators/bootstrap_generator_feature.rb +0 -11
  49. data/features/shoestrap/generators/kuhsaft_generator_feature.rb +0 -38
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9791492dd8bd44bbc69b59cee2871160915eccee
4
- data.tar.gz: 1f8a4e2e50a56425a0fc55cd561455fb0e944214
3
+ metadata.gz: 12d033c7ad061cb445baf6857013f73d608fb015
4
+ data.tar.gz: 943e058c89295660e1e5680aef2149d1bc623295
5
5
  SHA512:
6
- metadata.gz: 4d9896bbaff16d24ac9525b9894bdc7f579eb91f8a36f409c3336dd3abe4bdf276ed571937320c44dad34b0e6b453faf3dd8ad7026905736a8f6d6089f342047
7
- data.tar.gz: c0e40359529e4552bdf63fa84f4fcdfb4e0a64e726cfd3143fc0f9254087f6f048dfee0cf291a5590452a8a74c025a9edeaac18d8efd1e45534d1a170ed3cb95
6
+ metadata.gz: 52d6779e7fbd340f7ecb3c670070af01c71b10a0eb19857a39a4c50f83a9cc6e01b8789c930aa354a6e787d69942c950cb48dc52f78dac01dfb7ee168d70a536
7
+ data.tar.gz: 4781dec71bd2e0b45566e2bb309760c3e333f18dcc1915f6e0a080cce972899866526246c6f7f4a7825e39f2bc9ec68815a2bc2fd14d533c2717b4dda5fe2d5b
data/.gitignore CHANGED
@@ -16,3 +16,4 @@ test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
18
  project-notes.txt
19
+ features/test_app*
data/.travis.yml CHANGED
@@ -1,6 +1,5 @@
1
- ---
2
1
  rvm:
3
2
  - 2.0.0
4
3
  notifications:
5
4
  hipchat:
6
- secure: "RfG5xaMJ9Lgrusw9G34fqBd+AkHXWIEMFtwc4KRNUR4nfwLnuJi/Ekpkd2rc\n09CL19vm+uyHSL90PStSYZ7KLvYH7OGq/M1I0lLNZFTkCMnpNKyxwCr+Pk6l\nughm/FT0ablL7dE/isoDttRb6o//tpiv9sREib2DvIgzleciA0g="
5
+ secure: "hXZoShKmIMVc9kEvqJBkNAd3xba2LA64rB6Ra5mXPxHfp5wPTg2vx9GSeyuPUdpJlnSOGZB/SuTd7TMypn8Cd3TLBdKfepR8I68HH8YxZ1UCwZEoWLj8/iEoYdGZXqKbfiH/Vd7fnY+zSM9ucSpW/GZhDLLNSJwq8VXkBKqGrFM="
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## master
4
+
5
+ - Minor improvements on generating application layout
6
+ - make typekit key configurable
7
+
8
+ - Add minor tweaks to generated Gemfile
9
+ - remove hardcoded kuhsaft in template
10
+ - specify current shoestrap version
11
+ - add js runtime
12
+ - fix conditional tags for IE (thx to @kuschti)
13
+
3
14
  ## 1.0.0.pre1 - 2013-07-17
4
15
 
5
16
  Started from scratch for a clean, test driven implementation.
@@ -81,7 +92,7 @@ A few notable changes:
81
92
  * use human_attribute_name as label in 'show' template
82
93
  * remove title (h1) on 'show' template
83
94
  * use '[index_path_name].new' as translation key for new button on 'index' template
84
-
95
+
85
96
  ## 0.0.4
86
97
 
87
98
  * fix update/create actions in generated controller
data/Guardfile CHANGED
@@ -3,5 +3,6 @@ guard :rspec, :cli => "--color --format nested --fail-fast" do
3
3
  watch(%r|^lib/shoestrap.rb|) { "spec" }
4
4
  watch(%r|^spec/(.*)_spec\.rb|)
5
5
  watch(%r|^lib/(.*)([^/]+)\.rb|) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
6
+ # watch(%r{^features/.+_feature\.rb})
6
7
  watch(%r|^spec/spec_helper\.rb|) { "spec" }
7
8
  end
data/Rakefile CHANGED
@@ -11,7 +11,7 @@ end
11
11
  RSpec::Core::RakeTask.new(:features) do |t|
12
12
  t.rspec_opts = %w(--color --format nested)
13
13
  t.ruby_opts = %w(-w)
14
- t.pattern = 'features/**/*_feature.rb'
14
+ t.pattern = 'features/shoestrap/**/*_spec.rb'
15
15
  t.verbose = true
16
16
  end
17
17
 
data/circle.yml ADDED
@@ -0,0 +1,3 @@
1
+ test:
2
+ override:
3
+ - bundle exec rake
@@ -0,0 +1,94 @@
1
+ require_relative '../lib/shoestrap/application_generator'
2
+
3
+ def generate_test_app_with_shoestrap(options=nil)
4
+ ENV['SHOESTRAP_PATH'] = File.join(File.dirname(__FILE__), '..')
5
+
6
+ if options.is_a?(Hash)
7
+ aggregated_options = []
8
+ options.each_pair {|k,v| aggregated_options << "--#{k}=#{v}" }
9
+ options = aggregated_options.join(' ')
10
+ aggregated_options = nil
11
+ end
12
+
13
+ app_identifier = test_app_key(options)
14
+ puts if debug_shoestrap?
15
+ dbg_comment "[ app with options #{options.inspect} will be known as #{app_identifier.inspect} ]"
16
+ dbg_comment "[ app without any options would be known as #{test_app_key(nil).inspect} ]" unless options.blank?
17
+ if Postgres.create_user app_identifier
18
+ dbg_comment "successfully created postgres user #{app_identifier.inspect}"
19
+ else
20
+ dbg_comment "Won't create user #{app_identifier.inspect} while he already exists."
21
+ end
22
+
23
+ app_path = test_app_path(options)
24
+ result = nil
25
+
26
+ if target_app_path || File.exists?(app_path)
27
+ if File.exists?(app_path)
28
+ dbg_comment "Application path exists. I will just create the databases now. Pay attention if you have a task that makes something database related."
29
+ Dir.chdir(app_path) do
30
+ reload_application_gemfile options
31
+ Postgres.create_user app_identifier
32
+
33
+ # destroy all scaffolds
34
+ Dir['app/models/*.rb','app/models/cms/*.rb'].each do |path|
35
+ model_name = File.basename(path).gsub(File.extname(path),'')
36
+ drop_shoestrap_scaffold_for model_name, options
37
+ end
38
+
39
+ result = bundle_exec 'rake db:drop db:create db:migrate db:seed'
40
+ end
41
+ end
42
+ else
43
+ dbg_comment "generating test app in #{app_path}"
44
+ result = bundle_exec shoestrap_new(options)
45
+ end
46
+ puts if debug_shoestrap?
47
+ result
48
+ end
49
+
50
+ def shoestrap_new(options = nil)
51
+ "#{shoestrap_bin_path} new #{test_app_path(options)} #{options}"
52
+ end
53
+
54
+ [:rails, :rake].each do |command|
55
+ define_method command do |task, options = nil|
56
+ app_path = test_app_path(options)
57
+ Dir.chdir(app_path) do
58
+ dbg_comment "cd #{app_path}"
59
+ reload_application_gemfile options
60
+ bundle_exec "#{command} #{task}"
61
+ end
62
+ end
63
+ end
64
+
65
+ def bundle_exec(command)
66
+ if debug_shoestrap?
67
+ puts "#{ts} $ bundle exec #{command}"
68
+ outstr, errstr, status = Open3.capture3('bundle', 'exec', command)
69
+
70
+ # a²: why are info-messages in error out?
71
+ errstr = errstr.split("\n").select{|l| !l.blank? && !(l =~ /^\s*\d\d?:\d\d?:\d\d? - INFO -/) }.join("\n")
72
+
73
+ if errstr.present?
74
+ puts "there where errors while executing the command"
75
+ puts "\e[0;31m"+errstr.strip+"\e[0m"
76
+ puts
77
+ caller.select{|cl| !cl =~ /\/ruby\/gems\// }.each{|called_line| puts called_line }
78
+ puts
79
+ end
80
+ outstr
81
+ # dbg_comment "command #{command.inspect} finished"
82
+ else
83
+ `bundle exec #{command}`
84
+ end
85
+ end
86
+
87
+ def dbg_comment( msg )
88
+ return unless debug_shoestrap?
89
+ puts " # #{ts} - #{msg}"
90
+ end
91
+
92
+ def ts
93
+ Time.now.strftime('%H:%M:%S')
94
+ end
@@ -0,0 +1,23 @@
1
+ module FeatureMatcher
2
+
3
+ RSpec::Matchers.define :include_gem do |gem_name|
4
+ match do |gemfile|
5
+ if gem_name.include? ','
6
+ gem_name, gem_version = gem_name.split(',').map(&:strip)
7
+ # gem "shoestrap", "1.0.0.pre1"
8
+ gemfile =~ /gem\s+['"]#{gem_name}['"]\s*,\s*['"]#{gem_version}['"]/m
9
+ else
10
+ gemfile =~ /gem\s+['"]#{gem_name}['"]/m
11
+ end
12
+ end
13
+
14
+ failure_message_for_should do |gemfile|
15
+ "#{gem_name} should be in Gemfile"
16
+ end
17
+
18
+ failure_message_for_should_not do |gemfile|
19
+ "#{gem_name} should not be found in Gemfile"
20
+ end
21
+ end
22
+
23
+ end
@@ -1,44 +1,49 @@
1
- require 'rspec'
2
- require 'fileutils'
3
- require 'digest'
4
- require 'pry'
1
+ [
2
+ 'rspec', 'fileutils', 'digest', 'pry', 'open3'
3
+ ].each {|lib| require lib }
5
4
 
6
- RSpec.configure do |c|
7
- c.after(:suite) do
8
- clean_up
9
- end
10
- end
5
+ [
6
+ './postgres_helper', './custom_matcher', './command_wrapper_helper'
7
+ ].each {|lib| require_relative lib }
11
8
 
12
9
  # TODO: spec these helpers!
13
10
 
14
- def generate_test_app_with_shoestrap(options=nil)
15
- `createuser -s #{test_app_key(options)}`
16
- unless ENV['TARGET_APP'] || File.exists?(test_app_path(options))
17
- if ENV['DEBUG']
18
- puts "generating test app in #{test_app_path(options)}"
19
- puts "#{File.join(File.dirname(__FILE__), '../bin/shoestrap')} new #{test_app_path(options)} #{options}"
20
- system "#{File.join(File.dirname(__FILE__), '../bin/shoestrap')} new #{test_app_path(options)} #{options}"
21
- else
22
- `#{File.join(File.dirname(__FILE__), '../bin/shoestrap')} new #{test_app_path(options)} #{options}`
11
+ JUST_GENERATE_NEW_APP_IF_THESE_ARE_CHANGED = [
12
+ 'lib',
13
+ 'templates'
14
+ ]
15
+
16
+ def filetree_fingerprint(dirlist = JUST_GENERATE_NEW_APP_IF_THESE_ARE_CHANGED)
17
+ aggregated_hashes = ''
18
+ [dirlist].flatten.sort.each do |dir|
19
+ Dir[File.join(shoestrap_path, dir, '**/**')].sort.each do |f|
20
+ aggregated_hashes << (File.directory?(f) ? filetree_fingerprint(f) : Digest::MD5.hexdigest(File.read f).to_s)
23
21
  end
24
22
  end
23
+ Digest::MD5.hexdigest(aggregated_hashes).to_s
25
24
  end
26
25
 
27
26
  def reload_application_gemfile(options=nil)
28
- ENV['BUNDLE_GEMFILE'] = File.join(application_path(options), 'Gemfile')
29
- require 'bundler'
30
- Bundler.require(:default)
27
+ gemfile_path = File.join(application_path(options), 'Gemfile')
28
+ # dbg_comment "loading Gemfile #{gemfile_path.inspect}; given options #{options.inspect}"
29
+ ENV['BUNDLE_GEMFILE'] = gemfile_path
31
30
  end
32
31
 
33
32
  def clean_up
34
33
  puts
35
34
  puts 'cleaning up...'
36
35
  remove_test_dbs
37
- remove_test_apps
36
+ drop_database_from_dummy_apps
37
+ remove_test_apps if on_ci_system?
38
+ ENV.delete 'SHOESTRAP_PATH'
38
39
  puts
39
40
  puts
40
41
  end
41
42
 
43
+ def drop_database_from_dummy_apps
44
+ Postgres.drop_users_like 'test_app%'
45
+ end
46
+
42
47
  def test_apps
43
48
  Dir.entries(File.join(File.dirname(__FILE__))).select do |entry|
44
49
  entry.include? 'test_app'
@@ -55,11 +60,33 @@ end
55
60
  def remove_test_dbs
56
61
  test_apps.each do |app|
57
62
  Dir.chdir app do
58
- puts "dropping test db for #{app}" if ENV['DEBUG']
63
+ next unless Postgres.database_exists?(app.split('/').last + '_test')
64
+ puts "dropping test db for #{app}" if debug_shoestrap?
59
65
  ENV['BUNDLE_GEMFILE'] = File.join(Dir.pwd, 'Gemfile')
60
66
  require 'bundler'
61
67
  Bundler.require(:default)
62
- `bundle exec rake db:drop`
68
+ bundle_exec 'rake db:drop'
69
+ end
70
+ end
71
+ Postgres.drop_databases_like('test_app_%')
72
+ end
73
+
74
+ def drop_shoestrap_scaffold_for(name, options = nil)
75
+ %w(production development test).each do |db_env|
76
+ app_path = test_app_path(options)
77
+ unless File.exists? app_path
78
+ dbg_comment "won't destroy scaffold for #{name.inspect} while app #{app_path} doesn't exist."
79
+ return
80
+ end
81
+
82
+ Dir.chdir(app_path) do
83
+ database_name = app_path.split('/').last
84
+ rails "destroy scaffold #{name}", options
85
+ rails "destroy scaffold cms/#{name}", options
86
+ database = "#{database_name}_#{db_env}"
87
+ next unless Postgres.database_exists? database
88
+ # Postgres.select_database database
89
+ Postgres.drop_table database_name, database, name
63
90
  end
64
91
  end
65
92
  end
@@ -68,6 +95,14 @@ def application_path(options = nil)
68
95
  target_app_path || test_app_path(options)
69
96
  end
70
97
 
98
+ def shoestrap_path
99
+ File.expand_path(File.join(File.dirname(__FILE__),'../'))
100
+ end
101
+
102
+ def shoestrap_bin_path
103
+ File.join(shoestrap_path, 'bin/shoestrap')
104
+ end
105
+
71
106
  def target_app_path
72
107
  ENV['TARGET_APP']
73
108
  end
@@ -81,11 +116,23 @@ def application_file(file, options = nil)
81
116
  end
82
117
 
83
118
  def test_app_key(options)
84
- "test_app#{options.to_s.digest}"
119
+ app_hash = options.to_s.strip.gsub(/\W+/,'') + filetree_fingerprint
120
+ # a²: we need to limit the size due to maximum database name sizes in postgres
121
+ "test_app_#{(app_hash.size > 42) ? Digest::MD5.hexdigest(app_hash) : app_hash}"[0..42]
85
122
  end
86
123
 
87
- class String
88
- def digest
89
- "_#{Digest::MD5.hexdigest(self)}" unless self.empty?
90
- end
124
+ def debug_shoestrap?; !!ENV['DEBUG'] end
125
+
126
+ def on_ci_system?
127
+ ENV['TRAVIS'] || ENV['CI'] || ENV['CIRCLECI']
91
128
  end
129
+
130
+ RSpec.configure do |config|
131
+ config.include(FeatureMatcher)
132
+ config.after(:suite) do
133
+ clean_up
134
+ end
135
+ config.before(:suite) do
136
+ remove_test_apps if ENV['REMOVE_CACHE_AT_FIRST']
137
+ end
138
+ end
@@ -0,0 +1,69 @@
1
+ module Postgres
2
+ class << self
3
+ def exec(query, opts = {})
4
+ command = ["psql -tAc \"#{query}\""]
5
+
6
+ if opts.is_a?(Hash)
7
+ opts.each_pair {|k,v| command << "--#{k}=#{v}" }
8
+ else
9
+ command << opts
10
+ end
11
+
12
+ command = command.join(' ')
13
+ puts "#{ts} $ #{command}" if debug_shoestrap?
14
+ result = `#{command}`
15
+ if result.match(/psql: FATAL: database .+ does not exist/)
16
+ if result.include?("psql: FATAL: database \"#{`whoami`.strip}\" does not exist")
17
+ `createdb`
18
+ dbg_comment "user database was missing. I created it for you and recall the postgres command again. :)"
19
+ `#{command}`
20
+ end
21
+ else
22
+ result
23
+ end
24
+ end
25
+
26
+ def user_exists?(username)
27
+ exec("SELECT 1 FROM pg_user WHERE usename='#{username}'", {dbname: 'postgres'}).strip == '1'
28
+ end
29
+
30
+ def database_exists?(name)
31
+ exec("SELECT 1 from pg_database WHERE datname='#{name}'", {dbname: 'postgres'}).strip == '1'
32
+ end
33
+
34
+ def drop_user(username)
35
+ puts "#{ts} $ dropuser #{username}" if debug_shoestrap?
36
+ `dropuser #{username}`
37
+ end
38
+
39
+ def drop_table(user, database, name)
40
+ exec("SET client_min_messages TO WARNING; DROP TABLE IF EXISTS #{name};", {username: user, dbname: database})
41
+ end
42
+
43
+ def select_users_like(username)
44
+ exec("SELECT usename FROM pg_user where usename LIKE '#{username}'", {dbname: 'postgres'}).split("\n").map{|u| u.strip }
45
+ end
46
+
47
+ def select_databases_like(name)
48
+ exec("SELECT datname FROM pg_database WHERE datistemplate = false AND datname LIKE '#{name}';", {dbname: 'postgres'}).split("\n").map{|u| u.strip }
49
+ end
50
+
51
+ def drop_databases_like(name)
52
+ select_databases_like(name).each{|dbname| `dropdb #{dbname}` }
53
+ end
54
+
55
+ def drop_users_like(username)
56
+ select_users_like(username).each{|u| drop_user u if user_exists?(u) }
57
+ end
58
+
59
+ def create_user(username)
60
+ if user_exists?(username)
61
+ false
62
+ else
63
+ puts "#{ts} $ createuser -s #{username}" if debug_shoestrap?
64
+ `createuser -s #{username}`
65
+ end
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,234 @@
1
+ require_relative '../../features_helper'
2
+
3
+ describe 'application generated with shoestrap new <application_name>' do
4
+ before :all do
5
+ generate_test_app_with_shoestrap
6
+ end
7
+
8
+ let (:gemfile_content) { application_file('Gemfile') }
9
+ let (:application_rb_content) { application_file('config/application.rb') }
10
+ let (:application_layout) { application_file('app/views/layouts/application.html.haml') }
11
+ let (:application_layout_typekit) { application_file('app/views/layouts/_typekit.html.haml') }
12
+ let (:application_helper) { application_file('app/helpers/application_helper.rb') }
13
+ let (:development_rb_content) { application_file('config/environments/development.rb') }
14
+
15
+ it 'has timezone set for switzerland' do
16
+ expect(application_rb_content).to match(/config.time_zone = 'Bern'/)
17
+ end
18
+
19
+ it 'has :de as default locale' do
20
+ expect(application_rb_content).to match(/config.i18n.default_locale = :de/)
21
+ end
22
+
23
+ it 'has :de as only available locale for a satrt' do
24
+ expect(application_rb_content).to match(/config.i18n.available_locales = \[:de\]/)
25
+ end
26
+
27
+ it 'has translation files load path' do
28
+ expect(application_rb_content).to match(/config.i18n.load_path \+= Dir\[Rails.root.join\('config', 'locales', '\*\*', '\*.{rb,yml}'\).to_s\]/)
29
+ end
30
+
31
+ it 'has the shoestrap version in test set to the current path in Gemfile' do
32
+ expect(gemfile_content.split("\n")).to include("gem \"shoestrap\", path: \"#{Dir.pwd + '/features/..'}\"")
33
+ end
34
+
35
+ it 'has the typekit key set to false' do
36
+ expect(application_rb_content).to match(/config.typekit_key = false/)
37
+ end
38
+
39
+ # TODO: fix this in rails. Gems added with gem method of app template have double quotes!
40
+
41
+ %w[
42
+ simple_form
43
+ haml
44
+ haml-rails
45
+ simple-navigation
46
+ mail
47
+ fabrication
48
+ kuhsaft
49
+ selectivizr-rails
50
+ modernizr-rails
51
+ bourbon
52
+ therubyracer
53
+ shoestrap
54
+ inherited_resources
55
+ ].each do |gem_name|
56
+ it "has #{gem_name} in the Gemfile" do
57
+ expect(gemfile_content).to include_gem(gem_name)
58
+ end
59
+ end
60
+
61
+ %w[
62
+ pry
63
+ database_cleaner
64
+ guard-rspec
65
+ guard-spring
66
+ rspec-rails
67
+ mailcatcher
68
+ ].each do |gem_name|
69
+ it "has #{gem_name} in the Gemfile" do
70
+ expect(gemfile_content).to include_gem(gem_name)
71
+ end
72
+ end
73
+
74
+ it 'has the pg gem in the Gemfile' do
75
+ expect(gemfile_content).to include_gem('pg')
76
+ end
77
+
78
+ context 'application layout' do
79
+ it 'has no application layout written in erb' do
80
+ expect { application_file('app/views/layouts/application.html.erb') }.to raise_error(Errno::ENOENT)
81
+ end
82
+
83
+ it 'has an application layout written in haml' do
84
+ expect(application_layout).not_to be_nil
85
+ end
86
+
87
+ it 'sets the html lang' do
88
+ expect(application_layout).to match "%html.no-js{ lang: I18n.locale }"
89
+ end
90
+
91
+ it 'sets a page title' do
92
+ expect(application_layout).to match(/%title=\ content_for\?\(:title\)\ \?\ yield\(:title\)\ :\ 'Untitled'/)
93
+ end
94
+
95
+ it 'has meta tags' do
96
+ expect(application_layout).to match "%meta{ charset: 'utf-8' }"
97
+ expect(application_layout).to match "%meta{ 'http-equiv' => 'X-UA-Compatible', content: 'IE=edge,chrome=1' }"
98
+ expect(application_layout).to match "%meta{ name: 'keywords', content: '' }"
99
+ expect(application_layout).to match "%meta{ name: 'description', content: '' }"
100
+ expect(application_layout).to match "%meta{ name: 'viewport', content: 'width=device-width, initial-scale=1.0' }"
101
+ expect(application_layout).to match "= csrf_meta_tags"
102
+ end
103
+
104
+ it 'has favicons' do
105
+ expect(application_layout).to match(/favicon_link_tag\('favicons\/favicon\-sc\-129x129\.png',\ rel:\ 'apple\-touch\-icon',\ type:\ 'image\/png'\)/)
106
+ expect(application_layout).to match(/favicon_link_tag\('favicons\/favicon\-sc\-32x32\.png',\ rel:\ 'icon',\ type:\ 'image\/png'\)/)
107
+ expect(application_layout).to match(/favicon_link_tag\('favicons\/favicon\-sc\-16x16\.ico'\)/)
108
+ end
109
+
110
+ it 'has an application stylehseet link' do
111
+ expect(application_layout).to match "= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true"
112
+ end
113
+
114
+ it 'has javascript links' do
115
+ expect(application_layout).to match "= javascript_include_tag 'modernizr', 'data-turbolinks-track' => true"
116
+ expect(application_layout).to match "= javascript_include_tag 'application', 'data-turbolinks-track' => true"
117
+ expect(application_layout).to match "= javascript_include_tag 'selectivizr'"
118
+ end
119
+
120
+ it 'has a body class helper included' do
121
+ expect(application_layout).to match "%body{ class: body_class }"
122
+ end
123
+
124
+ it 'renders the navigation' do
125
+ expect(application_layout).to match "= render_navigation"
126
+ end
127
+
128
+ it 'renders the content' do
129
+ expect(application_layout).to match "= yield"
130
+ end
131
+
132
+ it 'renders the typekit' do
133
+ expect(application_layout).to match "= render 'layouts/typekit'"
134
+ end
135
+
136
+ it 'has google analytics integrated' do
137
+ expect(application_layout).to match(/var\ _gaq=\[\['_setAccount','UA\-XXXXX\-X'\],\['_trackPageview'\],\['_trackPageLoadTime'\]\];/)
138
+ expect(application_layout).to match(/\(function\(d,t\)\{var\ g=d\.createElement\(t\),s=d\.getElementsByTagName\(t\)\[0\];g\.async=1;/)
139
+ expect(application_layout).to match(/g\.src=\('https:'==location\.protocol\?'\/\/ssl':'\/\/www'\)\+'\.google\-analytics\.com\/ga\.js';/)
140
+ expect(application_layout).to match(/s\.parentNode\.insertBefore\(g,s\)\}\(document,'script'\)\);/)
141
+ end
142
+ end
143
+
144
+ context 'documentation file' do
145
+
146
+ it 'contains proper documentation' do
147
+ pending "implement proper readme template"
148
+ expect(application_file('README.md')).not_to match('README would normally document whatever steps are necessary to get the')
149
+ end
150
+ end
151
+
152
+ context 'favicons' do
153
+ it 'has a favicon' do
154
+ expect(application_file('app/assets/images/favicons/favicon-sc-32x32.png')).not_to be_nil
155
+ end
156
+
157
+ it 'has a favicon for iDevices' do
158
+ expect(application_file('app/assets/images/favicons/favicon-sc-129x129.png')).not_to be_nil
159
+ end
160
+
161
+ it 'has a favicton for IE' do
162
+ expect(application_file('app/assets/images/favicons/favicon-sc-16x16.ico')).not_to be_nil
163
+ end
164
+ end
165
+
166
+ context 'layout partials' do
167
+ it 'has a typekit partial' do
168
+ expect(application_layout_typekit).not_to be_nil
169
+ end
170
+
171
+ context 'typekit partial' do
172
+ it 'checks for typekit_key configuration' do
173
+ expect(application_layout_typekit).to match "- if Rails.application.config.typekit_key.present?"
174
+ end
175
+
176
+ it 'has the typekit js integrated' do
177
+ expect(application_layout_typekit).to match(/javascript_include_tag\ "\/\/use\.typekit\.net\/\#\{Rails\.application\.config\.typekit_key\}\.js",\ :media\ =>\ 'all'/)
178
+ expect(application_layout_typekit).to match(/try\{Typekit\.load\(\);\}catch\(e\)\{\}/)
179
+ end
180
+ end
181
+ end
182
+
183
+ context 'application helper' do
184
+ it 'has an application layout written in haml' do
185
+ expect(application_helper).not_to be_nil
186
+ end
187
+
188
+ it 'has a body_class method' do
189
+ expect(application_helper).to match "def body_class"
190
+ end
191
+ end
192
+
193
+ context 'generators' do
194
+ it 'use haml as a template engine' do
195
+ expect(application_rb_content).to match "g.template_engine :haml"
196
+ end
197
+
198
+ it 'use rspec as test framework' do
199
+ expect(application_rb_content).to match "test_framework :rspec"
200
+ end
201
+
202
+ it 'do not generate stylesheets' do
203
+ expect(application_rb_content).to match "g.stylesheets false"
204
+ end
205
+
206
+ it 'do not generate javascripts' do
207
+ expect(application_rb_content).to match "g.javascripts false"
208
+ end
209
+
210
+ it 'do not generate assets' do
211
+ expect(application_rb_content).to match "g.assets false"
212
+ end
213
+
214
+ it 'does not generate helpers' do
215
+ expect(application_rb_content).to match "g.helper false"
216
+ end
217
+
218
+ it 'uses simple_form as form builder' do
219
+ expect(application_rb_content).to match(/form_builder :simple_form/)
220
+ end
221
+
222
+
223
+ context 'mailcatcher' do
224
+ it 'is configured for development environment' do
225
+ expect(development_rb_content).to match(/config\.action_mailer\.delivery_method = :smtp/)
226
+ expect(development_rb_content).to match(/config\.action_mailer\.smtp_settings = { address: 'localhost', port: 1025 }/)
227
+ end
228
+
229
+ it 'is documented in the readme' do
230
+ expect(application_file('README.md')).to match(/This application uses Mailcatcher/)
231
+ end
232
+ end
233
+ end
234
+ end