potassium 5.2.1 → 6.2.0

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 (122) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +84 -0
  3. data/.gitignore +2 -1
  4. data/.node-version +1 -0
  5. data/.rubocop.yml +530 -0
  6. data/.ruby-version +1 -1
  7. data/CHANGELOG.md +91 -0
  8. data/README.md +41 -47
  9. data/docs/DSL.md +5 -5
  10. data/lib/potassium/assets/.buildpacks +0 -1
  11. data/lib/potassium/assets/.circleci/config.yml.erb +102 -0
  12. data/lib/potassium/assets/.eslintrc.json +352 -0
  13. data/lib/potassium/assets/.github/pull_request_template.md +9 -0
  14. data/lib/potassium/assets/.pryrc +1 -1
  15. data/lib/potassium/assets/.rubocop.yml +528 -0
  16. data/lib/potassium/assets/.stylelintrc.json +46 -0
  17. data/lib/potassium/assets/Dockerfile.ci +1 -1
  18. data/lib/potassium/assets/Makefile.erb +21 -32
  19. data/lib/potassium/assets/Procfile +1 -0
  20. data/lib/potassium/assets/README.yml +58 -11
  21. data/lib/potassium/assets/active_admin/admin-component.vue +35 -0
  22. data/lib/potassium/assets/active_admin/admin_application.js +14 -0
  23. data/lib/potassium/assets/active_admin/init_activeadmin_vue.rb +10 -0
  24. data/lib/potassium/assets/app/graphql/graphql_controller.rb +55 -0
  25. data/lib/potassium/assets/app/graphql/mutations/login_mutation.rb +23 -0
  26. data/lib/potassium/assets/app/graphql/queries/base_query.rb +4 -0
  27. data/lib/potassium/assets/app/graphql/types/base/base_argument.rb +4 -0
  28. data/lib/potassium/assets/app/graphql/types/base/base_enum.rb +4 -0
  29. data/lib/potassium/assets/app/graphql/types/base/base_field.rb +5 -0
  30. data/lib/potassium/assets/app/graphql/types/base/base_input_object.rb +5 -0
  31. data/lib/potassium/assets/app/graphql/types/base/base_interface.rb +7 -0
  32. data/lib/potassium/assets/app/graphql/types/base/base_object.rb +5 -0
  33. data/lib/potassium/assets/app/graphql/types/base/base_scalar.rb +4 -0
  34. data/lib/potassium/assets/app/graphql/types/base/base_union.rb +4 -0
  35. data/lib/potassium/assets/app/graphql/types/mutation_type.rb +10 -0
  36. data/lib/potassium/assets/app/graphql/types/query_type.rb +13 -0
  37. data/lib/potassium/assets/app/javascript/app.spec.js +14 -0
  38. data/lib/potassium/assets/app/uploaders/base_uploader.rb +11 -0
  39. data/lib/potassium/assets/app/uploaders/image_uploader.rb +5 -0
  40. data/lib/potassium/assets/app/views/shared/_gtm_body.html.erb +4 -0
  41. data/lib/potassium/assets/app/views/shared/_gtm_head.html.erb +7 -0
  42. data/lib/potassium/assets/bin/cibuild.erb +24 -7
  43. data/lib/potassium/assets/bin/release +9 -0
  44. data/lib/potassium/assets/bin/setup.erb +1 -1
  45. data/lib/potassium/assets/config/database_mysql.yml.erb +2 -2
  46. data/lib/potassium/assets/config/database_postgresql.yml.erb +2 -2
  47. data/lib/potassium/assets/config/graphql_playground.rb +20 -0
  48. data/lib/potassium/assets/config/puma.rb +1 -1
  49. data/lib/potassium/assets/config/shrine.rb +36 -0
  50. data/lib/potassium/assets/docker-compose.ci.yml +2 -1
  51. data/lib/potassium/assets/lib/tasks/auto_annotate_models.rake +34 -33
  52. data/lib/potassium/assets/package.json +4 -1
  53. data/lib/potassium/assets/redis.yml +1 -2
  54. data/lib/potassium/assets/testing/rails_helper.rb +4 -2
  55. data/lib/potassium/cli/commands/create.rb +12 -19
  56. data/lib/potassium/cli_options.rb +77 -26
  57. data/lib/potassium/helpers/gem-helpers.rb +1 -1
  58. data/lib/potassium/helpers/template-helpers.rb +4 -0
  59. data/lib/potassium/newest_version_ensurer.rb +19 -36
  60. data/lib/potassium/node_version_ensurer.rb +30 -0
  61. data/lib/potassium/recipes/admin.rb +3 -3
  62. data/lib/potassium/recipes/annotate.rb +1 -1
  63. data/lib/potassium/recipes/api.rb +93 -21
  64. data/lib/potassium/recipes/background_processor.rb +66 -19
  65. data/lib/potassium/recipes/ci.rb +6 -4
  66. data/lib/potassium/recipes/data_migrate.rb +44 -0
  67. data/lib/potassium/recipes/database.rb +4 -0
  68. data/lib/potassium/recipes/database_container.rb +7 -5
  69. data/lib/potassium/recipes/draper.rb +1 -10
  70. data/lib/potassium/recipes/file_storage.rb +66 -0
  71. data/lib/potassium/recipes/front_end.rb +219 -9
  72. data/lib/potassium/recipes/github.rb +93 -15
  73. data/lib/potassium/recipes/google_tag_manager.rb +90 -0
  74. data/lib/potassium/recipes/heroku.rb +44 -30
  75. data/lib/potassium/recipes/mailer.rb +27 -4
  76. data/lib/potassium/recipes/node.rb +21 -0
  77. data/lib/potassium/recipes/rack_cors.rb +18 -15
  78. data/lib/potassium/recipes/schedule.rb +17 -2
  79. data/lib/potassium/recipes/style.rb +21 -3
  80. data/lib/potassium/recipes/vue_admin.rb +124 -0
  81. data/lib/potassium/templates/application.rb +9 -7
  82. data/lib/potassium/version.rb +6 -4
  83. data/potassium.gemspec +11 -6
  84. data/spec/features/api_spec.rb +25 -0
  85. data/spec/features/background_processor_spec.rb +19 -6
  86. data/spec/features/data_migrate_spec.rb +14 -0
  87. data/spec/features/database_container_spec.rb +2 -5
  88. data/spec/features/draper_spec.rb +1 -6
  89. data/spec/features/file_storage_spec.rb +75 -0
  90. data/spec/features/front_end_spec.rb +88 -0
  91. data/spec/features/github_spec.rb +53 -8
  92. data/spec/features/google_tag_manager_spec.rb +59 -0
  93. data/spec/features/graphql_spec.rb +71 -0
  94. data/spec/features/heroku_spec.rb +8 -5
  95. data/spec/features/mailer_spec.rb +58 -0
  96. data/spec/features/new_project_spec.rb +6 -14
  97. data/spec/features/node_spec.rb +28 -0
  98. data/spec/features/power_types_spec.rb +5 -16
  99. data/spec/features/schedule_spec.rb +11 -4
  100. data/spec/features/vue_admin_spec.rb +47 -0
  101. data/spec/spec_helper.rb +5 -0
  102. data/spec/support/fake_octokit.rb +31 -0
  103. data/spec/support/potassium_test_helpers.rb +26 -9
  104. data/tmp/.keep +0 -0
  105. metadata +157 -48
  106. data/circle.yml +0 -12
  107. data/lib/potassium/assets/.circleci/config.yml +0 -20
  108. data/lib/potassium/assets/active_admin/active_admin.js.coffee +0 -4
  109. data/lib/potassium/assets/active_admin/init_activeadmin_angular.rb +0 -8
  110. data/lib/potassium/assets/api/api_error_concern.rb +0 -32
  111. data/lib/potassium/assets/api/base_controller.rb +0 -9
  112. data/lib/potassium/assets/api/draper_responder.rb +0 -62
  113. data/lib/potassium/assets/api/responder.rb +0 -41
  114. data/lib/potassium/assets/aws.rb +0 -1
  115. data/lib/potassium/assets/sidekiq_scheduler.yml +0 -9
  116. data/lib/potassium/assets/testing/paperclip.rb +0 -59
  117. data/lib/potassium/recipes/active_storage.rb +0 -40
  118. data/lib/potassium/recipes/angular_admin.rb +0 -56
  119. data/lib/potassium/recipes/aws_sdk.rb +0 -7
  120. data/lib/potassium/recipes/paperclip.rb +0 -47
  121. data/spec/features/active_storage_spec.rb +0 -30
  122. data/spec/features/front_end.rb +0 -30
@@ -1,7 +1,7 @@
1
1
  class Recipes::Ci < Rails::AppBuilder
2
2
  def create
3
3
  copy_file '../assets/Dockerfile.ci', 'Dockerfile.ci'
4
- copy_file '../assets/.circleci/config.yml', '.circleci/config.yml'
4
+ template '../assets/.circleci/config.yml.erb', '.circleci/config.yml'
5
5
 
6
6
  template '../assets/bin/cibuild.erb', 'bin/cibuild'
7
7
  run "chmod a+x bin/cibuild"
@@ -36,11 +36,13 @@ class Recipes::Ci < Rails::AppBuilder
36
36
  YAML
37
37
  compose.add_service("postgresql", srv)
38
38
  compose.add_link('test', 'postgresql')
39
- compose.add_env('test', 'POSTGRESQL_USER', 'postgres')
40
- compose.add_env('test', 'POSTGRESQL_HOST', 'postgresql')
41
- compose.add_env('test', 'POSTGRESQL_PORT', '5432')
39
+ compose.add_env('test', 'DB_USER', 'postgres')
40
+ compose.add_env('test', 'DB_HOST', 'postgresql')
41
+ compose.add_env('test', 'DB_PORT', '5432')
42
42
  end
43
43
 
44
+ compose.add_volume('test_data')
45
+
44
46
  add_readme_header :ci
45
47
 
46
48
  application 'config.assets.js_compressor = :uglifier', env: 'test'
@@ -0,0 +1,44 @@
1
+ class Recipes::DataMigrate < Rails::AppBuilder
2
+ def create
3
+ gather_gem('data_migrate')
4
+ annotate_task = 'lib/tasks/auto_annotate_models.rake'
5
+ insert_into_file annotate_task, annotate_config, after: "Annotate.load_tasks\n"
6
+ end
7
+
8
+ def install
9
+ create
10
+ end
11
+
12
+ def installed?
13
+ gem_exists?(/data_migrate/)
14
+ end
15
+
16
+ private
17
+
18
+ def annotate_config
19
+ <<-RUBY
20
+
21
+ data_migrate_tasks = %w(
22
+ db:migrate:with_data
23
+ db:migrate:up:with_data
24
+ db:migrate:down:with_data
25
+ db:migrate:redo:with_data
26
+ db:rollback:with_data
27
+ )
28
+
29
+ data_migrate_tasks.each do |task|
30
+ Rake::Task[task].enhance do
31
+ Rake::Task[Rake.application.top_level_tasks.last].enhance do
32
+ annotation_options_task = if Rake::Task.task_defined?('app:set_annotation_options')
33
+ 'app:set_annotation_options'
34
+ else
35
+ 'set_annotation_options'
36
+ end
37
+ Rake::Task[annotation_options_task].invoke
38
+ Annotate::Migration.update_annotations
39
+ end
40
+ end
41
+ end
42
+ RUBY
43
+ end
44
+ end
@@ -46,5 +46,9 @@ class Recipes::Database < Rails::AppBuilder
46
46
  else
47
47
  gather_gem db[:gem_name]
48
48
  end
49
+
50
+ after(:gem_install) do
51
+ generate 'strong_migrations:install'
52
+ end
49
53
  end
50
54
  end
@@ -24,20 +24,21 @@ class Recipes::DatabaseContainer < Rails::AppBuilder
24
24
  environment:
25
25
  MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
26
26
  volumes:
27
- - mysql_data:/var/lib/mysql
27
+ - mysql_data:/var/lib/mysql
28
28
  YAML
29
29
 
30
30
  def create
31
- copy_file '../assets/docker-compose.yml', 'docker-compose.yml'
31
+ db_type = get(:database)
32
+ return if [:None, :none].include? db_type.to_sym
32
33
 
34
+ copy_file '../assets/docker-compose.yml', 'docker-compose.yml'
33
35
  compose = DockerHelpers.new('docker-compose.yml')
34
36
 
35
- db_type = get(:database)
36
37
  compose.add_service(db_type.to_s, self.class.const_get("#{db_type}_service".upcase))
37
38
  compose.add_volume("#{db_type}_data")
38
39
  template '../assets/Makefile.erb', 'Makefile'
39
40
 
40
- run 'make services-up'
41
+ run "docker-compose up -d"
41
42
 
42
43
  set_env(db_type, CONTAINER_VARS[db_type][:port], CONTAINER_VARS[db_type][:user])
43
44
  set_dot_env(db_type, CONTAINER_VARS[db_type][:port], CONTAINER_VARS[db_type][:user])
@@ -53,11 +54,12 @@ class Recipes::DatabaseContainer < Rails::AppBuilder
53
54
  setup_text = # setup file is templated on project creation, manual install is needed
54
55
  <<~TEXT
55
56
  # Set up required services
56
- make services-up
57
+ docker-compose up -d
57
58
 
58
59
  TEXT
59
60
 
60
61
  insert_into_file 'bin/setup', setup_text, before: "# Set up database"
62
+ create
61
63
  run 'bin/setup'
62
64
  info "A new container with a #{get(:database)} database has been created."
63
65
  end
@@ -7,7 +7,6 @@ class Recipes::Draper < Rails::AppBuilder
7
7
  def create
8
8
  return unless selected?(:draper)
9
9
  add_draper
10
- add_api_responder if selected?(:api_support)
11
10
  end
12
11
 
13
12
  def installed?
@@ -16,19 +15,11 @@ class Recipes::Draper < Rails::AppBuilder
16
15
 
17
16
  def install
18
17
  add_draper
19
- api_recipe = load_recipe(:api)
20
- add_api_responder if api_recipe.installed?
21
18
  end
22
19
 
23
20
  def add_draper
24
- gather_gem 'draper', '3.0.1'
21
+ gather_gem 'draper', '~> 3.1'
25
22
  add_readme_section :internal_dependencies, :draper
26
23
  create_file 'app/decorators/.keep'
27
24
  end
28
-
29
- def add_api_responder
30
- after(:gem_install) do
31
- copy_file '../assets/api/draper_responder.rb', 'app/responders/api_responder.rb', force: true
32
- end
33
- end
34
25
  end
@@ -0,0 +1,66 @@
1
+ class Recipes::FileStorage < Rails::AppBuilder
2
+ def ask
3
+ storages = {
4
+ active_storage: 'ActiveStorage',
5
+ shrine: 'Shrine',
6
+ none: 'None, thanks'
7
+ }
8
+
9
+ storage = answer(:storage) do
10
+ storages.keys[Ask.list('Which storage are you going to use?', storages.values)]
11
+ end
12
+
13
+ set(:storage, storage.to_sym)
14
+ end
15
+
16
+ def create
17
+ add_chosen_storage
18
+ end
19
+
20
+ def install
21
+ ask
22
+ add_chosen_storage
23
+ end
24
+
25
+ def installed?
26
+ file_exist?('config/storage.yml')
27
+ end
28
+
29
+ private
30
+
31
+ def add_active_storage
32
+ after(:gem_install) { run('bundle exec rails active_storage:install') }
33
+ copy_file('../assets/config/storage.yml', 'config/storage.yml', force: true)
34
+ active_storage_service_regexp = /config.active_storage.service = :local\n/
35
+ gsub_file 'config/environments/production.rb', active_storage_service_regexp do
36
+ 'config.active_storage.service = :amazon'
37
+ end
38
+ end
39
+
40
+ def add_shrine
41
+ gather_gem('shrine', '~> 3.0')
42
+ gather_gem('marcel', '~> 0.3.3')
43
+ copy_file('../assets/config/shrine.rb', 'config/initializers/shrine.rb', force: true)
44
+ copy_file('../assets/app/uploaders/image_uploader.rb', 'app/uploaders/image_uploader.rb')
45
+ copy_file('../assets/app/uploaders/base_uploader.rb', 'app/uploaders/base_uploader.rb')
46
+ append_to_file('.gitignore', "/public/uploads\n")
47
+ end
48
+
49
+ def common_setup
50
+ gather_gem 'aws-sdk-s3', '~> 1.0'
51
+ add_readme_section :internal_dependencies, get(:storage)
52
+ append_to_file '.env.development', "S3_BUCKET=\n"
53
+ end
54
+
55
+ def add_chosen_storage
56
+ return if [:none, :None].include? get(:storage).to_sym
57
+
58
+ common_setup
59
+ case get(:storage)
60
+ when :active_storage
61
+ add_active_storage
62
+ when :shrine
63
+ add_shrine
64
+ end
65
+ end
66
+ end
@@ -17,22 +17,22 @@ class Recipes::FrontEnd < Rails::AppBuilder
17
17
  def create
18
18
  return if [:none, :None].include? get(:front_end).to_sym
19
19
 
20
- gather_gem 'webpacker', github: 'rails/webpacker'
21
-
20
+ recipe = self
22
21
  after(:gem_install) do
23
22
  value = get(:front_end)
24
23
  run "rails webpacker:install"
25
24
  run "rails webpacker:install:#{value}" if value
26
25
 
27
26
  if value == :vue
28
- application_js_file = "app/javascript/packs/application.js"
29
- FileUtils.move "app/javascript/packs/hello_vue.js", application_js_file
30
- gsub_file application_js_file, %r{\/\/.*\n}, ""
31
-
32
- js_pack_tag = "\n <%= javascript_pack_tag 'application' %>\n"
33
- layout_file = "app/views/layouts/application.html.erb"
34
- insert_into_file layout_file, js_pack_tag, after: "<%= csrf_meta_tags %>"
27
+ recipe.setup_vue_with_compiler_build
28
+ recipe.setup_jest
29
+ if get(:api) == :graphql
30
+ recipe.setup_apollo
31
+ end
35
32
  end
33
+ recipe.add_responsive_meta_tag
34
+ recipe.setup_tailwind
35
+ add_readme_header :webpack
36
36
  end
37
37
  end
38
38
 
@@ -48,6 +48,65 @@ class Recipes::FrontEnd < Rails::AppBuilder
48
48
  package_content.include?("\"@angular/core\"") || package_content.include?("\"vue\"")
49
49
  end
50
50
 
51
+ def setup_vue_with_compiler_build
52
+ application_js = 'app/javascript/packs/application.js'
53
+ remove_file "app/javascript/packs/hello_vue.js"
54
+ create_file application_js, application_js_content, force: true
55
+
56
+ layout_file = "app/views/layouts/application.html.erb"
57
+ insert_into_file(
58
+ layout_file,
59
+ "<div id=\"vue-app\">\n <app></app>\n ",
60
+ before: "<%= yield %>"
61
+ )
62
+ insert_into_file layout_file, "\n </div>", after: "<%= yield %>"
63
+ end
64
+
65
+ def add_responsive_meta_tag
66
+ tag = "\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n"
67
+ layout_file = "app/views/layouts/application.html.erb"
68
+ insert_into_file layout_file, tag, after: "<%= csrf_meta_tags %>"
69
+ end
70
+
71
+ def setup_tailwind
72
+ run 'bin/yarn add tailwindcss'
73
+ setup_client_css
74
+ remove_server_css_requires
75
+ setup_tailwind_requirements
76
+ end
77
+
78
+ def setup_jest
79
+ run 'bin/yarn add jest vue-jest babel-jest @vue/test-utils jest-serializer-vue babel-core@^7.0.0-bridge.0 --dev'
80
+ json_file = File.read(Pathname.new("package.json"))
81
+ js_package = JSON.parse(json_file)
82
+ js_package = js_package.merge(jest_config)
83
+ json_string = JSON.pretty_generate(js_package)
84
+ create_file 'package.json', json_string, force: true
85
+
86
+ copy_file '../assets/app/javascript/app.spec.js', 'app/javascript/app.spec.js'
87
+ end
88
+
89
+ def setup_apollo
90
+ run 'bin/yarn add vue-apollo graphql apollo-client apollo-link apollo-link-http apollo-cache-inmemory graphql-tag'
91
+
92
+ inject_into_file(
93
+ 'app/javascript/packs/application.js',
94
+ apollo_imports,
95
+ after: "import App from '../app.vue';"
96
+ )
97
+
98
+ inject_into_file(
99
+ 'app/javascript/packs/application.js',
100
+ apollo_loading,
101
+ after: "import VueApollo from 'vue-apollo';"
102
+ )
103
+ inject_into_file(
104
+ 'app/javascript/packs/application.js',
105
+ "\n apolloProvider,",
106
+ after: "components: { App },"
107
+ )
108
+ end
109
+
51
110
  private
52
111
 
53
112
  def frameworks(framework)
@@ -58,4 +117,155 @@ class Recipes::FrontEnd < Rails::AppBuilder
58
117
  }
59
118
  frameworks[framework]
60
119
  end
120
+
121
+ def apollo_imports
122
+ <<~JS
123
+ \n
124
+ import { ApolloClient } from 'apollo-client';
125
+ import { createHttpLink } from 'apollo-link-http';
126
+ import { InMemoryCache } from 'apollo-cache-inmemory';
127
+ import VueApollo from 'vue-apollo';
128
+ JS
129
+ end
130
+
131
+ def apollo_loading
132
+ <<~JS
133
+ \n
134
+ const httpLink = createHttpLink({
135
+ uri: `${window.location.origin}/graphql`,
136
+ })
137
+ const cache = new InMemoryCache()
138
+ const apolloClient = new ApolloClient({
139
+ link: httpLink,
140
+ cache,
141
+ })
142
+
143
+ Vue.use(VueApollo)
144
+ const apolloProvider = new VueApollo({
145
+ defaultClient: apolloClient,
146
+ })
147
+ JS
148
+ end
149
+
150
+ def setup_client_css
151
+ application_css = 'app/javascript/css/application.css'
152
+ create_file application_css, "", force: true
153
+
154
+ stylesheet_pack_tag = "\n <%= stylesheet_pack_tag 'application' %>\n "
155
+ layout_file = "app/views/layouts/application.html.erb"
156
+ insert_into_file layout_file, stylesheet_pack_tag, before: "</head>"
157
+
158
+ application_js = 'app/javascript/packs/application.js'
159
+ if get(:front_end) != :vue
160
+ create_file application_js, "import '../css/application.css';\n", force: true
161
+ else
162
+ insert_into_file(
163
+ application_js,
164
+ "\nimport '../css/application.css';",
165
+ after: "import App from '../app.vue';"
166
+ )
167
+ end
168
+ end
169
+
170
+ def setup_tailwind_requirements
171
+ application_css = 'app/javascript/css/application.css'
172
+ insert_into_file application_css, tailwind_client_css
173
+
174
+ tailwind_config = 'tailwind.config.js'
175
+ create_file tailwind_config, tailwind_config_content, force: true
176
+
177
+ postcss_file = 'postcss.config.js'
178
+ insert_into_file postcss_file, postcss_require_tailwind, after: "plugins: [\n"
179
+ end
180
+
181
+ def remove_server_css_requires
182
+ assets_css_file = 'app/assets/stylesheets/application.css'
183
+ gsub_file(assets_css_file, " *= require_tree .\n *= require_self\n", "")
184
+ end
185
+
186
+ def application_js_content
187
+ <<~JS
188
+ import Vue from 'vue/dist/vue.esm';
189
+ import App from '../app.vue';
190
+
191
+ document.addEventListener('DOMContentLoaded', () => {
192
+ const app = new Vue({
193
+ el: '#vue-app',
194
+ components: { App },
195
+ });
196
+
197
+ return app;
198
+ });
199
+ JS
200
+ end
201
+
202
+ def tailwind_client_css
203
+ <<~CSS
204
+ @import 'tailwindcss/base';
205
+ @import 'tailwindcss/components';
206
+ @import 'tailwindcss/utilities';
207
+ CSS
208
+ end
209
+
210
+ def tailwind_config_content
211
+ <<~JS
212
+ /* eslint-disable no-undef */
213
+ module.exports = {
214
+ theme: {
215
+ extend: {},
216
+ },
217
+ variants: {},
218
+ plugins: [],
219
+ purge: {
220
+ enabled: process.env.NODE_ENV === 'production',
221
+ content: [
222
+ './app/**/*.html',
223
+ './app/**/*.vue',
224
+ './app/**/*.js',
225
+ './app/**/*.erb',
226
+ ],
227
+ }
228
+ };
229
+ JS
230
+ end
231
+
232
+ def postcss_require_tailwind
233
+ <<-JS.gsub(/^ {4}/, ' ')
234
+ require('tailwindcss'),
235
+ require('autoprefixer'),
236
+ JS
237
+ end
238
+
239
+ def jest_config
240
+ {
241
+ "scripts": {
242
+ "test": "jest",
243
+ "test:watch": "jest --watch"
244
+ },
245
+ "jest": {
246
+ "roots": [
247
+ "app/javascript"
248
+ ],
249
+ "moduleDirectories": [
250
+ "node_modules",
251
+ "app/javascript"
252
+ ],
253
+ "moduleNameMapper": {
254
+ "^@/(.*)$": "app/javascript/$1"
255
+ },
256
+ "moduleFileExtensions": [
257
+ "js",
258
+ "json",
259
+ "vue"
260
+ ],
261
+ "transform": {
262
+ "^.+\\.js$": "<rootDir>/node_modules/babel-jest",
263
+ ".*\\.(vue)$": "<rootDir>/node_modules/vue-jest"
264
+ },
265
+ "snapshotSerializers": [
266
+ "<rootDir>/node_modules/jest-serializer-vue"
267
+ ]
268
+ }
269
+ }
270
+ end
61
271
  end