potassium 5.2.0 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +42 -0
  3. data/.editorconfig +3 -0
  4. data/.node-version +1 -0
  5. data/.ruby-version +1 -1
  6. data/CHANGELOG.md +94 -0
  7. data/README.md +41 -47
  8. data/docs/DSL.md +5 -5
  9. data/lib/potassium/assets/.buildpacks +0 -1
  10. data/lib/potassium/assets/.circleci/config.yml.erb +102 -0
  11. data/lib/potassium/assets/.eslintrc.json +352 -0
  12. data/lib/potassium/assets/.github/pull_request_template.md +9 -0
  13. data/lib/potassium/assets/.pryrc +1 -1
  14. data/lib/potassium/assets/.rubocop.yml +515 -0
  15. data/lib/potassium/assets/.stylelintrc.json +46 -0
  16. data/lib/potassium/assets/Dockerfile.ci +1 -1
  17. data/lib/potassium/assets/Makefile.erb +35 -0
  18. data/lib/potassium/assets/Procfile +1 -0
  19. data/lib/potassium/assets/README.yml +60 -11
  20. data/lib/potassium/assets/active_admin/admin-component.vue +35 -0
  21. data/lib/potassium/assets/active_admin/admin_application.js +14 -0
  22. data/lib/potassium/assets/active_admin/init_activeadmin_vue.rb +10 -0
  23. data/lib/potassium/assets/app/graphql/graphql_controller.rb +55 -0
  24. data/lib/potassium/assets/app/graphql/mutations/login_mutation.rb +23 -0
  25. data/lib/potassium/assets/app/graphql/queries/base_query.rb +4 -0
  26. data/lib/potassium/assets/app/graphql/types/base/base_argument.rb +4 -0
  27. data/lib/potassium/assets/app/graphql/types/base/base_enum.rb +4 -0
  28. data/lib/potassium/assets/app/graphql/types/base/base_field.rb +5 -0
  29. data/lib/potassium/assets/app/graphql/types/base/base_input_object.rb +5 -0
  30. data/lib/potassium/assets/app/graphql/types/base/base_interface.rb +7 -0
  31. data/lib/potassium/assets/app/graphql/types/base/base_object.rb +5 -0
  32. data/lib/potassium/assets/app/graphql/types/base/base_scalar.rb +4 -0
  33. data/lib/potassium/assets/app/graphql/types/base/base_union.rb +4 -0
  34. data/lib/potassium/assets/app/graphql/types/mutation_type.rb +10 -0
  35. data/lib/potassium/assets/app/graphql/types/query_type.rb +13 -0
  36. data/lib/potassium/assets/app/javascript/app.spec.js +14 -0
  37. data/lib/potassium/assets/app/uploaders/base_uploader.rb +11 -0
  38. data/lib/potassium/assets/app/uploaders/image_uploader.rb +5 -0
  39. data/lib/potassium/assets/bin/cibuild.erb +24 -7
  40. data/lib/potassium/assets/bin/release +9 -0
  41. data/lib/potassium/assets/bin/setup.erb +3 -0
  42. data/lib/potassium/assets/config/database_mysql.yml.erb +5 -5
  43. data/lib/potassium/assets/config/database_postgresql.yml.erb +5 -5
  44. data/lib/potassium/assets/config/graphql_playground.rb +20 -0
  45. data/lib/potassium/assets/config/puma.rb +5 -1
  46. data/lib/potassium/assets/config/shrine.rb +36 -0
  47. data/lib/potassium/assets/docker-compose.ci.yml +2 -1
  48. data/lib/potassium/assets/docker-compose.yml +6 -0
  49. data/lib/potassium/assets/lib/tasks/auto_annotate_models.rake +34 -33
  50. data/lib/potassium/assets/package.json +4 -1
  51. data/lib/potassium/assets/redis.yml +1 -2
  52. data/lib/potassium/assets/sidekiq_scheduler.yml +1 -1
  53. data/lib/potassium/assets/testing/rails_helper.rb +4 -2
  54. data/lib/potassium/cli/commands/create.rb +12 -19
  55. data/lib/potassium/cli_options.rb +67 -24
  56. data/lib/potassium/helpers/docker-helpers.rb +14 -5
  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 +38 -2
  65. data/lib/potassium/recipes/ci.rb +8 -6
  66. data/lib/potassium/recipes/data_migrate.rb +44 -0
  67. data/lib/potassium/recipes/database.rb +6 -2
  68. data/lib/potassium/recipes/database_container.rb +90 -0
  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/heroku.rb +2 -1
  74. data/lib/potassium/recipes/listen.rb +7 -0
  75. data/lib/potassium/recipes/mailer.rb +14 -4
  76. data/lib/potassium/recipes/node.rb +21 -0
  77. data/lib/potassium/recipes/puma.rb +0 -3
  78. data/lib/potassium/recipes/rack_cors.rb +18 -15
  79. data/lib/potassium/recipes/rails.rb +6 -0
  80. data/lib/potassium/recipes/schedule.rb +1 -1
  81. data/lib/potassium/recipes/style.rb +21 -3
  82. data/lib/potassium/recipes/vue_admin.rb +124 -0
  83. data/lib/potassium/templates/application.rb +10 -9
  84. data/lib/potassium/version.rb +7 -4
  85. data/potassium.gemspec +9 -6
  86. data/spec/features/api_spec.rb +25 -0
  87. data/spec/features/background_processor_spec.rb +12 -1
  88. data/spec/features/data_migrate_spec.rb +14 -0
  89. data/spec/features/database_container_spec.rb +35 -0
  90. data/spec/features/draper_spec.rb +1 -6
  91. data/spec/features/file_storage_spec.rb +75 -0
  92. data/spec/features/front_end_spec.rb +88 -0
  93. data/spec/features/github_spec.rb +53 -8
  94. data/spec/features/graphql_spec.rb +71 -0
  95. data/spec/features/heroku_spec.rb +8 -5
  96. data/spec/features/mailer_spec.rb +42 -0
  97. data/spec/features/new_project_spec.rb +6 -14
  98. data/spec/features/node_spec.rb +28 -0
  99. data/spec/features/power_types_spec.rb +5 -16
  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 -8
  104. metadata +126 -45
  105. data/circle.yml +0 -12
  106. data/lib/potassium/assets/.circleci/config.yml +0 -20
  107. data/lib/potassium/assets/active_admin/active_admin.js.coffee +0 -4
  108. data/lib/potassium/assets/active_admin/init_activeadmin_angular.rb +0 -8
  109. data/lib/potassium/assets/api/api_error_concern.rb +0 -32
  110. data/lib/potassium/assets/api/base_controller.rb +0 -9
  111. data/lib/potassium/assets/api/draper_responder.rb +0 -62
  112. data/lib/potassium/assets/api/responder.rb +0 -41
  113. data/lib/potassium/assets/aws.rb +0 -1
  114. data/lib/potassium/assets/testing/paperclip.rb +0 -59
  115. data/lib/potassium/recipes/active_storage.rb +0 -40
  116. data/lib/potassium/recipes/angular_admin.rb +0 -56
  117. data/lib/potassium/recipes/aws_sdk.rb +0 -7
  118. data/lib/potassium/recipes/paperclip.rb +0 -47
  119. data/spec/features/active_storage_spec.rb +0 -30
  120. data/spec/features/front_end.rb +0 -30
@@ -30,8 +30,8 @@ class Recipes::Database < Rails::AppBuilder
30
30
 
31
31
  def databases(database)
32
32
  databases = {
33
- postgresql: { name: 'postgresql', gem_name: 'pg', version: '~> 0.21', relational: true },
34
- mysql: { name: 'mysql', gem_name: 'mysql2', version: '~> 0.3.18', relational: true }
33
+ postgresql: { name: 'postgresql', gem_name: 'pg', relational: true },
34
+ mysql: { name: 'mysql', gem_name: 'mysql2', version: '~> 0.5.0', relational: true }
35
35
  }
36
36
  databases[database]
37
37
  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
@@ -0,0 +1,90 @@
1
+ class Recipes::DatabaseContainer < Rails::AppBuilder
2
+ CONTAINER_VARS = {
3
+ postgresql: { port: 5432, user: 'postgres' },
4
+ mysql: { port: 3306, user: 'root' }
5
+ }
6
+
7
+ POSTGRESQL_SERVICE =
8
+ <<~YAML
9
+ image: postgres:#{Potassium::POSTGRES_VERSION}
10
+ ports:
11
+ - #{CONTAINER_VARS[:postgresql][:port]}
12
+ environment:
13
+ POSTGRES_USER: #{CONTAINER_VARS[:postgresql][:user]}
14
+ POSTGRES_PASSWORD: ''
15
+ volumes:
16
+ - postgresql_data:/var/lib/postgresql/data
17
+ YAML
18
+
19
+ MYSQL_SERVICE =
20
+ <<~YAML
21
+ image: "mysql:#{Potassium::MYSQL_VERSION}"
22
+ ports:
23
+ - #{CONTAINER_VARS[:mysql][:port]}
24
+ environment:
25
+ MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
26
+ volumes:
27
+ - mysql_data:/var/lib/mysql
28
+ YAML
29
+
30
+ def create
31
+ db_type = get(:database)
32
+ return if [:None, :none].include? db_type.to_sym
33
+
34
+ copy_file '../assets/docker-compose.yml', 'docker-compose.yml'
35
+ compose = DockerHelpers.new('docker-compose.yml')
36
+
37
+ compose.add_service(db_type.to_s, self.class.const_get("#{db_type}_service".upcase))
38
+ compose.add_volume("#{db_type}_data")
39
+ template '../assets/Makefile.erb', 'Makefile'
40
+
41
+ run "docker-compose up -d"
42
+
43
+ set_env(db_type, CONTAINER_VARS[db_type][:port], CONTAINER_VARS[db_type][:user])
44
+ set_dot_env(db_type, CONTAINER_VARS[db_type][:port], CONTAINER_VARS[db_type][:user])
45
+ end
46
+
47
+ def install
48
+ database_config = YAML.safe_load(IO.read('config/database.yml'), [], [], true)
49
+ database = database_config['development']['adapter'].gsub(/\d+/, '').to_sym
50
+ set :database, database
51
+
52
+ template "../assets/config/database_#{database}.yml.erb", 'config/database.yml'
53
+
54
+ setup_text = # setup file is templated on project creation, manual install is needed
55
+ <<~TEXT
56
+ # Set up required services
57
+ docker-compose up -d
58
+
59
+ TEXT
60
+
61
+ insert_into_file 'bin/setup', setup_text, before: "# Set up database"
62
+ create
63
+ run 'bin/setup'
64
+ info "A new container with a #{get(:database)} database has been created."
65
+ end
66
+
67
+ def installed?
68
+ file_exist?("docker-compose.yml")
69
+ end
70
+
71
+ private
72
+
73
+ def set_env(_service_name, _port, _user)
74
+ ENV["DB_PORT"] = `make services-port SERVICE=#{_service_name} PORT=#{_port}`.squish
75
+ ENV["DB_USER"] = _user
76
+ end
77
+
78
+ def set_dot_env(_service_name, _port, _user)
79
+ env_text =
80
+ <<~TEXT
81
+
82
+ # Database
83
+ DB_HOST=127.0.0.1
84
+ DB_PORT=$(make services-port SERVICE=#{_service_name} PORT=#{_port})
85
+ DB_USER=#{_user}
86
+
87
+ TEXT
88
+ insert_into_file '.env.development', env_text, after: "WEB_CONCURRENCY=1\n"
89
+ end
90
+ 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