shoestrap 1.0.0.pre1 → 1.0.0.pre2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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