potassium 6.7.0 → 7.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +9 -1
  3. data/.node-version +1 -1
  4. data/.rubocop.yml +4 -0
  5. data/CHANGELOG.md +40 -0
  6. data/README.md +8 -1
  7. data/docs/CONTRIBUTING.md +6 -6
  8. data/lib/potassium/assets/.circleci/config.yml.erb +19 -13
  9. data/lib/potassium/assets/.env.development.erb +1 -0
  10. data/lib/potassium/assets/.env.test.erb +1 -0
  11. data/lib/potassium/assets/.eslintrc.json +14 -9
  12. data/lib/potassium/assets/.rubocop.yml +66 -1
  13. data/lib/potassium/assets/README.yml +3 -9
  14. data/lib/potassium/assets/app/frontend/active_admin/jquery.js +2 -0
  15. data/lib/potassium/assets/app/frontend/api/__mocks__/index.mock.ts +3 -0
  16. data/lib/potassium/assets/app/frontend/api/index.ts +63 -0
  17. data/lib/potassium/assets/app/frontend/css/application.css +3 -0
  18. data/lib/potassium/assets/app/frontend/entrypoints/active_admin.js +7 -0
  19. data/lib/potassium/assets/app/frontend/entrypoints/active_admin.scss +38 -0
  20. data/lib/potassium/assets/app/frontend/entrypoints/application.js +12 -0
  21. data/lib/potassium/assets/app/{javascript → frontend}/types/vue.d.ts +1 -0
  22. data/lib/potassium/assets/app/{javascript → frontend}/utils/case-converter.ts +2 -2
  23. data/lib/potassium/assets/app/frontend/utils/csrf-token.ts +9 -0
  24. data/lib/potassium/assets/bin/setup.erb +1 -1
  25. data/lib/potassium/assets/bin/update.erb +1 -1
  26. data/lib/potassium/assets/config/initializers/session_store.rb +20 -0
  27. data/lib/potassium/assets/config/sentry.rb.erb +2 -10
  28. data/lib/potassium/assets/lib/dotenv_monkeypatch.rb +19 -0
  29. data/lib/potassium/assets/lib/environment_variables.rb +9 -0
  30. data/lib/potassium/assets/package.json +7 -0
  31. data/lib/potassium/assets/tailwind.config.js +14 -0
  32. data/lib/potassium/assets/testing/simplecov_config.rb +10 -1
  33. data/lib/potassium/assets/tsconfig.config.json +18 -0
  34. data/lib/potassium/assets/tsconfig.json +17 -27
  35. data/lib/potassium/assets/vite.config.ts +46 -0
  36. data/lib/potassium/cli_options.rb +6 -4
  37. data/lib/potassium/helpers/rubocop-helpers.rb +6 -12
  38. data/lib/potassium/platanus_config.rb +1 -1
  39. data/lib/potassium/recipes/admin.rb +43 -72
  40. data/lib/potassium/recipes/background_processor.rb +0 -30
  41. data/lib/potassium/recipes/bullet.rb +41 -0
  42. data/lib/potassium/recipes/ci.rb +5 -0
  43. data/lib/potassium/recipes/cleanup.rb +0 -1
  44. data/lib/potassium/recipes/coverage.rb +4 -27
  45. data/lib/potassium/recipes/database_container.rb +1 -1
  46. data/lib/potassium/recipes/environment_variables.rb +18 -0
  47. data/lib/potassium/recipes/error_reporting.rb +2 -2
  48. data/lib/potassium/recipes/front_end_vite.rb +155 -0
  49. data/lib/potassium/recipes/google_tag_manager.rb +19 -23
  50. data/lib/potassium/recipes/mailer.rb +1 -1
  51. data/lib/potassium/recipes/mjml.rb +1 -1
  52. data/lib/potassium/recipes/node.rb +1 -1
  53. data/lib/potassium/recipes/rails.rb +2 -0
  54. data/lib/potassium/recipes/redis.rb +57 -0
  55. data/lib/potassium/recipes/style.rb +4 -6
  56. data/lib/potassium/recipes/vue_admin.rb +18 -14
  57. data/lib/potassium/recipes/yarn.rb +1 -1
  58. data/lib/potassium/templates/application.rb +11 -13
  59. data/lib/potassium/version.rb +8 -7
  60. data/spec/features/api_spec.rb +2 -2
  61. data/spec/features/background_processor_spec.rb +2 -2
  62. data/spec/features/bullet_spec.rb +29 -0
  63. data/spec/features/ci_spec.rb +17 -4
  64. data/spec/features/coverage_spec.rb +7 -10
  65. data/spec/features/database_container_spec.rb +1 -1
  66. data/spec/features/database_spec.rb +1 -1
  67. data/spec/features/draper_spec.rb +1 -1
  68. data/spec/features/environment_variables_spec.rb +28 -0
  69. data/spec/features/error_reporting_spec.rb +2 -2
  70. data/spec/features/file_storage_spec.rb +4 -4
  71. data/spec/features/google_tag_manager_spec.rb +1 -1
  72. data/spec/features/i18n_spec.rb +1 -1
  73. data/spec/features/mailer_spec.rb +1 -2
  74. data/spec/features/new_project_spec.rb +2 -8
  75. data/spec/features/node_spec.rb +1 -1
  76. data/spec/features/power_types_spec.rb +1 -1
  77. data/spec/features/pundit_spec.rb +1 -1
  78. data/spec/features/redis_spec.rb +43 -0
  79. data/spec/features/schedule_spec.rb +1 -1
  80. data/spec/features/testing_spec.rb +0 -1
  81. data/spec/features/vue_admin_spec.rb +1 -1
  82. data/spec/front_end_vite_spec.rb +79 -0
  83. data/spec/support/potassium_test_helpers.rb +0 -6
  84. metadata +36 -19
  85. data/lib/potassium/assets/app/javascript/api/index.ts +0 -55
  86. data/lib/potassium/assets/config/webpack/rules/css.js +0 -5
  87. data/lib/potassium/assets/config/webpack/rules/index.js +0 -11
  88. data/lib/potassium/assets/config/webpack/rules/jquery.js +0 -11
  89. data/lib/potassium/assets/config/webpack/rules/typescript.js +0 -32
  90. data/lib/potassium/assets/config/webpack/rules/vue.js +0 -19
  91. data/lib/potassium/assets/config/webpack/webpack.config.js +0 -4
  92. data/lib/potassium/recipes/front_end.rb +0 -270
  93. data/spec/features/front_end_spec.rb +0 -76
  94. /data/lib/potassium/assets/app/{javascript → frontend}/components/app.spec.ts +0 -0
  95. /data/lib/potassium/assets/app/{javascript → frontend}/components/app.vue +0 -0
@@ -0,0 +1,155 @@
1
+ class Recipes::FrontEndVite < Rails::AppBuilder
2
+ VUE_VERSION = Potassium::VUE_VERSION
3
+ POSTCSS_VERSION = Potassium::POSTCSS_VERSION
4
+ TAILWINDCSS_VERSION = Potassium::TAILWINDCSS_VERSION
5
+ AUTOPREFIXER_VERSION = Potassium::AUTOPREFIXER_VERSION
6
+ VUE_TEST_UTILS_VERSION = Potassium::VUE_TEST_UTILS_VERSION
7
+ JSDOM_VERSION = Potassium::JSDOM_VERSION
8
+
9
+ DEPENDENCIES = {
10
+ tailwind: [
11
+ "postcss@#{POSTCSS_VERSION}",
12
+ "tailwindcss@#{TAILWINDCSS_VERSION}",
13
+ "autoprefixer@#{AUTOPREFIXER_VERSION}",
14
+ "sass"
15
+ ],
16
+ typescript: [
17
+ "typescript"
18
+ ],
19
+ typescript_dev: [
20
+ "@types/node"
21
+ ],
22
+ vue: [
23
+ "vue@#{VUE_VERSION}"
24
+ ],
25
+ vue_dev: [
26
+ "@tsconfig/node14",
27
+ "@vitejs/plugin-vue",
28
+ "@vue/tsconfig",
29
+ "vue-tsc"
30
+ ],
31
+ vitest_dev: [
32
+ "vitest",
33
+ "@vue/test-utils@#{VUE_TEST_UTILS_VERSION}",
34
+ "jsdom@#{JSDOM_VERSION}"
35
+ ],
36
+ api: [
37
+ "axios",
38
+ "humps"
39
+ ],
40
+ api_dev: [
41
+ "@types/humps"
42
+ ]
43
+ }
44
+
45
+ def installed?
46
+ gem_exists?(/vite_rails/)
47
+ end
48
+
49
+ def create
50
+ add_vite
51
+ end
52
+
53
+ def install
54
+ add_vite
55
+ end
56
+
57
+ def add_vite
58
+ gather_gem("vite_rails")
59
+ recipe = self
60
+ after(:gem_install, wrap_in_action: :vite_install) do
61
+ run "yarn install"
62
+ run "bundle exec vite install"
63
+ recipe.install_packages
64
+ recipe.setup_tailwind
65
+ recipe.copy_config_files
66
+ recipe.setup_vite
67
+ recipe.copy_default_assets
68
+ recipe.insert_vue_into_layout
69
+ recipe.setup_api_client
70
+ add_readme_header :vite
71
+ end
72
+ end
73
+
74
+ def install_packages
75
+ packages, dev_packages = DEPENDENCIES.partition { |k, _| !k.to_s.end_with?('_dev') }.map(&:to_h)
76
+
77
+ run "yarn add #{packages.values.flatten.join(' ')}"
78
+ run "yarn add --dev #{dev_packages.values.flatten.join(' ')}"
79
+ end
80
+
81
+ def setup_tailwind
82
+ run "npx tailwindcss init -p"
83
+ end
84
+
85
+ def copy_config_files
86
+ copy_file '../assets/vite.config.ts', 'vite.config.ts', force: true
87
+ copy_file '../assets/tailwind.config.js', 'tailwind.config.js', force: true
88
+ copy_file '../assets/tsconfig.json', 'tsconfig.json', force: true
89
+ copy_file '../assets/tsconfig.config.json', 'tsconfig.config.json', force: true
90
+ end
91
+
92
+ def setup_vite
93
+ add_vite_dev_ws_content_security_policy
94
+ copy_dotenv_monkeypatch
95
+ end
96
+
97
+ def copy_default_assets
98
+ copy_file '../assets/app/frontend/entrypoints/application.js',
99
+ 'app/frontend/entrypoints/application.js', force: true
100
+ copy_file '../assets/app/frontend/css/application.css', 'app/frontend/css/application.css',
101
+ force: true
102
+ copy_file '../assets/app/frontend/components/app.vue', 'app/frontend/components/app.vue',
103
+ force: true
104
+ copy_file '../assets/app/frontend/types/vue.d.ts', 'app/frontend/types/vue.d.ts'
105
+ copy_file '../assets/app/frontend/components/app.spec.ts',
106
+ 'app/frontend/components/app.spec.ts'
107
+ end
108
+
109
+ def insert_vue_into_layout
110
+ layout_file = "app/views/layouts/application.html.erb"
111
+ insert_into_file(
112
+ layout_file,
113
+ "<div id=\"vue-app\">\n <app></app>\n ",
114
+ before: "<%= yield %>"
115
+ )
116
+ insert_into_file layout_file, "\n </div>", after: "<%= yield %>"
117
+ end
118
+
119
+ def setup_api_client
120
+ copy_file '../assets/app/frontend/api/index.ts', 'app/frontend/api/index.ts'
121
+ copy_file '../assets/app/frontend/api/__mocks__/index.mock.ts',
122
+ 'app/frontend/api/__mocks__/index.mock.ts'
123
+ copy_file '../assets/app/frontend/utils/case-converter.ts',
124
+ 'app/frontend/utils/case-converter.ts'
125
+ copy_file '../assets/app/frontend/utils/csrf-token.ts',
126
+ 'app/frontend/utils/csrf-token.ts'
127
+ end
128
+
129
+ def add_vite_dev_ws_content_security_policy
130
+ initializer = "config/initializers/content_security_policy.rb"
131
+ line = "# policy.style_src *policy.style_src, :unsafe_inline if Rails.env.development?"
132
+ policy = <<~HERE.chomp
133
+ # if Rails.env.development?
134
+ # policy.connect_src *policy.connect_src,
135
+ # "ws://\#{ViteRuby.config.host_with_port}"
136
+ # end
137
+ HERE
138
+ # check if policy already exists
139
+ return if File.read(initializer).include?("policy.connect_src *policy.connect_src")
140
+
141
+ inject_into_file initializer, after: line do
142
+ policy
143
+ end
144
+ end
145
+
146
+ def copy_dotenv_monkeypatch
147
+ copy_file '../assets/lib/dotenv_monkeypatch.rb',
148
+ 'lib/dotenv_monkeypatch.rb', force: true
149
+ insert_into_file(
150
+ "config/application.rb",
151
+ "\nrequire_relative '../lib/dotenv_monkeypatch'\n",
152
+ after: "Bundler.require(*Rails.groups)"
153
+ )
154
+ end
155
+ end
@@ -25,7 +25,8 @@ class Recipes::GoogleTagManager < Rails::AppBuilder
25
25
  def add_content_security_policy
26
26
  inject_into_file(
27
27
  'config/initializers/content_security_policy.rb',
28
- content_security_policy_code
28
+ content_security_policy_code,
29
+ before: '# Report violations without enforcing the policy.'
29
30
  )
30
31
  end
31
32
 
@@ -67,28 +68,23 @@ class Recipes::GoogleTagManager < Rails::AppBuilder
67
68
 
68
69
  def content_security_policy_code
69
70
  <<~HERE
70
- Rails.application.config.content_security_policy do |policy|
71
- policy.connect_src(
72
- :self,
73
- :https,
74
- 'http://localhost:3035',
75
- 'ws://localhost:3035',
76
- 'https://www.google-analytics.com'
77
- )
78
- # google tag manager requires to enable unsafe inline and vue unsave eval:
79
- # https://developers.google.com/tag-manager/web/csp
80
- # https://vuejs.org/v2/guide/installation.html#CSP-environments
81
- policy.script_src(
82
- :self,
83
- :https,
84
- :unsafe_inline,
85
- :unsafe_eval,
86
- 'https://www.googletagmanager.com',
87
- 'https://www.google-analytics.com',
88
- 'https://ssl.google-analytics.com'
89
- )
90
- policy.img_src :self, 'data:', :https, 'https://www.googletagmanager.com', 'https://www.google-analytics.com'
91
- end
71
+ # policy.connect_src(
72
+ # *policy.connect_src,
73
+ # 'https://www.google-analytics.com'
74
+ # )
75
+ # google tag manager requires to enable unsafe inline:
76
+ # https://developers.google.com/tag-manager/web/csp
77
+ # policy.script_src(
78
+ # *policy.script_src,
79
+ # 'https://www.googletagmanager.com',
80
+ # 'https://www.google-analytics.com',
81
+ # 'https://ssl.google-analytics.com'
82
+ # )
83
+ # policy.img_src(
84
+ # *policy.img_src,
85
+ # 'https://www.googletagmanager.com',
86
+ # 'https://www.google-analytics.com'
87
+ # )
92
88
  HERE
93
89
  end
94
90
  end
@@ -74,7 +74,7 @@ class Recipes::Mailer < Rails::AppBuilder
74
74
  RUBY
75
75
  application asset_host_prod, env: "production"
76
76
  mailer_config = <<~RUBY
77
- require Rails.root.join("config", "mailer")
77
+ require Rails.root.join("config/mailer")
78
78
  RUBY
79
79
 
80
80
  prepend_file "config/environments/production.rb", mailer_config
@@ -4,7 +4,7 @@ class Recipes::Mjml < Rails::AppBuilder
4
4
 
5
5
  gather_gem 'mjml-rails'
6
6
  after(:gem_install) do
7
- run 'bin/yarn add mjml'
7
+ run 'yarn add mjml'
8
8
  mjml_config
9
9
  end
10
10
  end
@@ -8,7 +8,7 @@ class Recipes::Node < Rails::AppBuilder
8
8
  def create
9
9
  info "Using node version LTS #{NODE_VERSION}"
10
10
  create_file '.node-version', NODE_VERSION, force: true
11
- after(:webpacker_install) do
11
+ after(:vite_install) do
12
12
  json_file = File.read(Pathname.new("package.json"))
13
13
  js_package = JSON.parse(json_file)
14
14
  js_package["engines"] = { "node" => "#{NODE_VERSION}.x" }
@@ -1,6 +1,8 @@
1
1
  class Recipes::Rails < Rails::AppBuilder
2
2
  def create
3
3
  gather_gem("bootsnap", require: false)
4
+ gather_gem("sassc", github: "sass/sassc-ruby", ref: 'refs/pull/233/head')
5
+ gather_gem("sassc-embedded")
4
6
  environment 'config.force_ssl = true', env: 'production'
5
7
  disable_automatic_nonce_generation
6
8
  end
@@ -0,0 +1,57 @@
1
+ class Recipes::Redis < Rails::AppBuilder
2
+ def create
3
+ add_redis
4
+ add_docker_compose_redis_config
5
+ set_redis_dot_env
6
+ add_session_store_config
7
+ end
8
+
9
+ def install
10
+ create
11
+ end
12
+
13
+ def installed?
14
+ gem_exists?(/redis-actionpack/)
15
+ end
16
+
17
+ def add_redis
18
+ run_action(:install_redis) do
19
+ gather_gem("redis-actionpack")
20
+ copy_file("../assets/redis.yml", "config/redis.yml", force: true)
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def add_docker_compose_redis_config
27
+ compose = DockerHelpers.new('docker-compose.yml')
28
+
29
+ service_definition =
30
+ <<~YAML
31
+ image: redis:6.2.12
32
+ ports:
33
+ - 6379
34
+ volumes:
35
+ - redis_data:/data
36
+ YAML
37
+
38
+ compose.add_service('redis', service_definition)
39
+ compose.add_volume('redis_data')
40
+ end
41
+
42
+ def set_redis_dot_env
43
+ append_to_file(
44
+ '.env.development',
45
+ <<~TEXT
46
+ REDIS_HOST=127.0.0.1
47
+ REDIS_PORT=COMMAND_EXPAND(make services-port SERVICE=redis PORT=6379)
48
+ REDIS_URL=redis://${REDIS_HOST}:${REDIS_PORT}/1
49
+ TEXT
50
+ )
51
+ end
52
+
53
+ def add_session_store_config
54
+ copy_file("../assets/config/initializers/session_store.rb",
55
+ "config/initializers/session_store.rb", force: true)
56
+ end
57
+ end
@@ -20,13 +20,11 @@ class Recipes::Style < Rails::AppBuilder
20
20
  gather_gem 'rubocop-platanus'
21
21
  end
22
22
 
23
- after(:webpacker_install) do
23
+ after(:vite_install) do
24
24
  run "yarn add --dev stylelint eslint eslint-plugin-import "\
25
- "@typescript-eslint/eslint-plugin @types/jest @typescript-eslint/parser "\
26
- "eslint-plugin-jest eslint-plugin-platanus"
27
- if selected?(:front_end, :vue)
28
- run 'yarn add --dev eslint-plugin-vue @vue/eslint-config-typescript'
29
- end
25
+ "@typescript-eslint/eslint-plugin @typescript-eslint/parser "\
26
+ "eslint-plugin-platanus eslint-plugin-vue @vue/eslint-config-typescript "\
27
+ "eslint-plugin-tailwindcss"
30
28
  end
31
29
  end
32
30
 
@@ -5,7 +5,6 @@ class Recipes::VueAdmin < Rails::AppBuilder
5
5
  Ask.confirm "Do you want Vue support for ActiveAdmin?"
6
6
  end
7
7
  set(:vue_admin, vue_admin)
8
- set(:front_end, :vue) if vue_admin
9
8
  end
10
9
  end
11
10
 
@@ -29,23 +28,18 @@ class Recipes::VueAdmin < Rails::AppBuilder
29
28
  end
30
29
 
31
30
  def installed?
32
- dir_exist?("app/assets/javascripts/admin")
31
+ file_exist?("lib/vue_component.rb")
33
32
  end
34
33
 
35
34
  def add_vue_admin
36
35
  add_vue_component_library
37
36
  add_component_integration
38
- js_line = 'import "activeadmin_addons"'
39
- gsub_file(
40
- 'app/javascript/active_admin.js',
41
- js_line,
42
- <<~HERE
43
- #{js_line}
44
- #{active_admin_js}
45
- HERE
37
+ insert_into_file(
38
+ 'app/frontend/entrypoints/active_admin.js',
39
+ active_admin_js
46
40
  )
47
41
  copy_file '../assets/active_admin/admin-component.vue',
48
- 'app/javascript/components/admin-component.vue',
42
+ 'app/frontend/components/admin-component.vue',
49
43
  force: true
50
44
  end
51
45
 
@@ -128,7 +122,7 @@ class Recipes::VueAdmin < Rails::AppBuilder
128
122
  def active_admin_js
129
123
  <<~HERE
130
124
  import { createApp } from 'vue';
131
- import AdminComponent from './components/admin-component.vue';
125
+ import AdminComponent from '../components/admin-component.vue';
132
126
 
133
127
  function onLoad() {
134
128
  if (document.getElementById('wrapper') !== null) {
@@ -141,8 +135,18 @@ class Recipes::VueAdmin < Rails::AppBuilder
141
135
  }));
142
136
  },
143
137
  });
144
- app.component('AdminComponent', AdminComponent);
145
- app.mount('#wrapper');
138
+ app.component('admin_component', AdminComponent);
139
+
140
+ // Avoid using '#wrapper' as the mount point, as that includes the entire admin page,
141
+ // which could be used for Client-Side Template Injection (CSTI) attacks. Limit the
142
+ // mount point to specific areas where you need Vue components.
143
+
144
+ // DO NOT mount Vue in elements that contain user input rendered by
145
+ // ActiveAdmin.
146
+ // By default ActiveAdmin doesn't escape {{ }} in user input, so it's
147
+ // possible to inject arbitrary JavaScript code into the page.
148
+
149
+ // app.mount('#wrapper');
146
150
  }
147
151
 
148
152
  return null;
@@ -1,6 +1,6 @@
1
1
  class Recipes::Yarn < Rails::AppBuilder
2
2
  def create
3
- template '../assets/package.json', 'package.json' unless get(:front_end)
3
+ template '../assets/package.json', 'package.json'
4
4
  template '../assets/bin/update.erb', 'bin/update', force: true
5
5
  application "config.assets.paths << Rails.root.join('node_modules')"
6
6
  append_to_file ".gitignore", "node_modules/\n"
@@ -4,24 +4,15 @@ set :titleized_app_name, get(:app_name).titleize
4
4
  set :underscorized_app_name, get(:app_name).underscore
5
5
  set :dasherized_app_name, get(:app_name).dasherize
6
6
 
7
- run_action(:after_create_rails) do
8
- rubocop_revision
9
- end
10
-
11
7
  run_action(:cleaning) do
12
8
  clean_gemfile
13
9
  end
14
10
 
15
- run_action(:add_utils) do
16
- gather_gem("enumerize")
17
- end
18
-
19
11
  run_action(:asking) do
20
12
  ask :database
21
13
  ask :devise
22
14
  ask :admin
23
15
  ask :google_tag_manager
24
- ask :front_end
25
16
  ask :vue_admin
26
17
  ask :mailer
27
18
  ask :background_processor
@@ -41,7 +32,6 @@ run_action(:recipe_loading) do
41
32
  create :spring
42
33
  create :readme
43
34
  create :heroku
44
- create :ci
45
35
  create :style
46
36
  create :puma
47
37
  create :env
@@ -55,6 +45,7 @@ run_action(:recipe_loading) do
55
45
  create :yarn
56
46
  create :editorconfig
57
47
  create :mailer
48
+ create :redis
58
49
  create :background_processor
59
50
  create :schedule
60
51
  create :i18n
@@ -76,12 +67,15 @@ run_action(:recipe_loading) do
76
67
  create :tzinfo
77
68
  create :script
78
69
  create :github
70
+ create :ci
79
71
  create :cleanup
80
- create :front_end
81
- create :admin
82
- create :vue_admin
83
72
  create :google_tag_manager
84
73
  create :mjml
74
+ create :bullet
75
+ create :front_end_vite
76
+ create :admin
77
+ create :vue_admin
78
+ create :environment_variables
85
79
  end
86
80
 
87
81
  info "Gathered enough information. Applying the template. Wait a minute."
@@ -95,3 +89,7 @@ run_action(:database_creation) do
95
89
  run "bundle exec rails db:create db:migrate"
96
90
  run "RACK_ENV=test bundle exec rails db:create db:migrate"
97
91
  end
92
+
93
+ run_action(:rubocop_revision) do
94
+ run_rubocop
95
+ end
@@ -1,17 +1,18 @@
1
1
  module Potassium
2
- VERSION = "6.7.0"
2
+ VERSION = "7.1.0"
3
3
  RUBY_VERSION = "2.7.0"
4
- RAILS_VERSION = "~> 6.1.4.4"
4
+ RAILS_VERSION = "~> 7.0.4.2"
5
5
  RUBOCOP_VERSION = "~> 1.9"
6
6
  RUBOCOP_RSPEC_VERSION = "~> 2.2"
7
7
  POSTGRES_VERSION = "11.3"
8
8
  MYSQL_VERSION = "5.7"
9
- NODE_VERSION = "14"
10
- TAILWINDCSS_VERSION = "^3"
11
- POSTCSS_VERSION = "^8"
12
- AUTOPREFIXER_VERSION = "^10"
9
+ NODE_VERSION = "20"
10
+ TAILWINDCSS_VERSION = "^3.2.7"
11
+ POSTCSS_VERSION = "^8.4.21"
12
+ AUTOPREFIXER_VERSION = "^10.4.13"
13
13
  VUE_VERSION = "^3.2.33"
14
14
  VUE_LOADER_VERSION = "^16.8.3"
15
15
  VUE_TEST_UTILS_VERSION = "^2.0.2"
16
- JEST_VERSION = "^28.0.1"
16
+ JEST_VERSION = "^29.0.0"
17
+ JSDOM_VERSION = "^21.1.2"
17
18
  end
@@ -9,8 +9,8 @@ RSpec.describe "Api" do
9
9
 
10
10
  it "adds power_api related gems to Gemfile" do
11
11
  gemfile_content = IO.read("#{project_path}/Gemfile")
12
- expect(gemfile_content).to include("gem 'power_api'")
13
- expect(gemfile_content).to include("gem 'rswag-specs'")
12
+ expect(gemfile_content).to include("power_api")
13
+ expect(gemfile_content).to include("rswag-specs")
14
14
  end
15
15
 
16
16
  it "adds the power_api brief to README file" do
@@ -11,7 +11,7 @@ RSpec.describe "BackgroundProcessor" do
11
11
 
12
12
  it "adds sidekiq gem to Gemfile" do
13
13
  gemfile_content = IO.read("#{project_path}/Gemfile")
14
- expect(gemfile_content).to include("gem 'sidekiq'")
14
+ expect(gemfile_content).to include("sidekiq")
15
15
  end
16
16
 
17
17
  it "adds queue_adapter to application.rb" do
@@ -43,7 +43,7 @@ RSpec.describe "BackgroundProcessor" do
43
43
  content = IO.read("#{project_path}/.env.development")
44
44
  expect(content).to include("DB_POOL=25")
45
45
  expect(content).to include('REDIS_HOST=127.0.0.1')
46
- expect(content).to include('REDIS_PORT=$(make services-port SERVICE=redis PORT=6379)')
46
+ expect(content).to include('REDIS_PORT=COMMAND_EXPAND(make services-port SERVICE=redis PORT=6379)')
47
47
  expect(content).to include('REDIS_URL=redis://${REDIS_HOST}:${REDIS_PORT}/1')
48
48
  end
49
49
 
@@ -0,0 +1,29 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "Bullet" do
4
+ before(:all) do
5
+ drop_dummy_database
6
+ remove_project_directory
7
+ create_dummy_project
8
+ end
9
+
10
+ context "with all the bullet config" do
11
+ let(:dev_config) { IO.read("#{project_path}/config/environments/development.rb") }
12
+
13
+ it { expect(dev_config).to include("config.after_initialize do") }
14
+ it { expect(dev_config).to include("Bullet.enable = true") }
15
+ it { expect(dev_config).to include("Bullet.alert = true") }
16
+ it { expect(dev_config).to include("Bullet.bullet_logger = true") }
17
+ it { expect(dev_config).to include("Bullet.console = true") }
18
+ it { expect(dev_config).to include("Bullet.rails_logger = true") }
19
+ it { expect(dev_config).to include("Bullet.add_footer = true") }
20
+ end
21
+
22
+ context "with bullet application job config" do
23
+ let(:application_job) { IO.read("#{project_path}/app/jobs/application_job.rb") }
24
+
25
+ it 'adds bullet configuration to application_job.rb' do
26
+ expect(application_job).to include(" include Bullet::ActiveJob if Rails.env.development?\n")
27
+ end
28
+ end
29
+ end
@@ -2,16 +2,29 @@ require "spec_helper"
2
2
  require "rubocop"
3
3
 
4
4
  RSpec.describe 'CI' do
5
+ let(:ci_config) do
6
+ yml_path = "#{project_path}/.circleci/config.yml"
7
+ IO.read(yml_path)
8
+ end
9
+
5
10
  before(:all) do
6
11
  drop_dummy_database
7
12
  remove_project_directory
8
13
  create_dummy_project
9
14
  end
10
15
 
16
+ it "adds brakeman to Gemfile" do
17
+ content = IO.read("#{project_path}/Gemfile")
18
+ expect(content).to include("brakeman")
19
+ end
20
+
11
21
  it "correctly bundles the config file" do
12
- yml_path = "#{project_path}/.circleci/config.yml"
13
- content = IO.read(yml_path)
14
- expect(File.exist?(yml_path)).to be true
15
- expect(content).to include('cimg/ruby', 'cache', 'rspec', 'reviewdog')
22
+ expect(ci_config).to include('cimg/ruby', 'cache', 'rspec', 'reviewdog', 'brakeman')
23
+ end
24
+
25
+ it "uses dasherized app name for repo analyzer" do
26
+ expect(ci_config).to include(
27
+ "repo_analyzer:analyze[platanus/#{PotassiumTestHelpers::APP_NAME.dasherize}]"
28
+ )
16
29
  end
17
30
  end
@@ -9,9 +9,9 @@ RSpec.describe "Coverage" do
9
9
 
10
10
  it "adds simplecov related gems to Gemfile" do
11
11
  content = IO.read("#{project_path}/Gemfile")
12
- expect(content).to include("gem 'simplecov'")
13
- expect(content).to include("gem 'simplecov_linter_formatter'")
14
- expect(content).to include("gem 'simplecov_text_formatter'")
12
+ expect(content).to include("simplecov")
13
+ expect(content).to include("simplecov_linter_formatter")
14
+ expect(content).to include("simplecov_text_formatter")
15
15
  end
16
16
 
17
17
  it "requires simplecov config file before rails" do
@@ -26,18 +26,15 @@ RSpec.describe "Coverage" do
26
26
 
27
27
  context "with vue" do
28
28
  let(:node_modules_file) { IO.read("#{project_path}/package.json") }
29
+ let(:vite_config) { IO.read("#{project_path}/vite.config.ts") }
29
30
 
30
31
  before(:all) do
31
32
  remove_project_directory
32
- create_dummy_project("front_end" => "vue")
33
+ create_dummy_project("front_end_vite" => true)
33
34
  end
34
35
 
35
- it "adds jest coverage configuration" do
36
- expect(node_modules_file).to include('"collectCoverage": true')
37
- end
38
-
39
- it "adds jest text formatter package" do
40
- expect(node_modules_file).to include('jest-text-formatter')
36
+ it "adds vitest coverage configuration" do
37
+ expect(vite_config).to include("provider: 'c8',")
41
38
  end
42
39
  end
43
40
  end
@@ -25,7 +25,7 @@ RSpec.describe "DatabaseContainer" do
25
25
  db_port = compose_content[:services][service_name][:ports].first
26
26
 
27
27
  expect(env_file)
28
- .to include("DB_PORT=$(make services-port SERVICE=#{service_name} PORT=#{db_port})")
28
+ .to include("DB_PORT=COMMAND_EXPAND(make services-port SERVICE=#{service_name} PORT=#{db_port})")
29
29
  expect(env_file).to include("DB_HOST=127.0.0.1")
30
30
  expect(File.exist?("#{project_path}/Makefile")).to be true
31
31
  expect(setup_file).to include("docker-compose up -d")
@@ -9,6 +9,6 @@ RSpec.describe "Database" do
9
9
 
10
10
  it "adds the Strong Migrations gem to Gemfile" do
11
11
  gemfile_content = IO.read("#{project_path}/Gemfile")
12
- expect(gemfile_content).to include("gem 'strong_migrations'")
12
+ expect(gemfile_content).to include("strong_migrations")
13
13
  end
14
14
  end
@@ -9,7 +9,7 @@ RSpec.describe "Draper" do
9
9
 
10
10
  it "adds the Draper gem to Gemfile" do
11
11
  gemfile_content = IO.read("#{project_path}/Gemfile")
12
- expect(gemfile_content).to include("gem 'draper'")
12
+ expect(gemfile_content).to include("draper")
13
13
  end
14
14
 
15
15
  it "adds the Draper brief to README file" do