potassium 6.0.0 → 6.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +103 -38
  3. data/.circleci/setup-rubygems.sh +3 -0
  4. data/.gitignore +2 -1
  5. data/.rubocop.yml +530 -0
  6. data/CHANGELOG.md +57 -0
  7. data/README.md +51 -45
  8. data/lib/potassium/assets/.circleci/config.yml.erb +83 -34
  9. data/lib/potassium/assets/.eslintrc.json +13 -4
  10. data/lib/potassium/assets/.github/pull_request_template.md +9 -0
  11. data/lib/potassium/assets/.rubocop.yml +13 -0
  12. data/lib/potassium/assets/README.yml +7 -7
  13. data/lib/potassium/assets/app/graphql/graphql_controller.rb +55 -0
  14. data/lib/potassium/assets/app/graphql/mutations/login_mutation.rb +23 -0
  15. data/lib/potassium/assets/app/graphql/queries/base_query.rb +4 -0
  16. data/lib/potassium/assets/app/graphql/types/base/base_argument.rb +4 -0
  17. data/lib/potassium/assets/app/graphql/types/base/base_enum.rb +4 -0
  18. data/lib/potassium/assets/app/graphql/types/base/base_field.rb +5 -0
  19. data/lib/potassium/assets/app/graphql/types/base/base_input_object.rb +5 -0
  20. data/lib/potassium/assets/app/graphql/types/base/base_interface.rb +7 -0
  21. data/lib/potassium/assets/app/graphql/types/base/base_object.rb +5 -0
  22. data/lib/potassium/assets/app/graphql/types/base/base_scalar.rb +4 -0
  23. data/lib/potassium/assets/app/graphql/types/base/base_union.rb +4 -0
  24. data/lib/potassium/assets/app/graphql/types/mutation_type.rb +10 -0
  25. data/lib/potassium/assets/app/graphql/types/query_type.rb +13 -0
  26. data/lib/potassium/assets/app/javascript/app.spec.js +1 -1
  27. data/lib/potassium/assets/app/uploaders/base_uploader.rb +1 -3
  28. data/lib/potassium/assets/app/views/shared/_gtm_body.html.erb +4 -0
  29. data/lib/potassium/assets/app/views/shared/_gtm_head.html.erb +7 -0
  30. data/lib/potassium/assets/config/graphql_playground.rb +20 -0
  31. data/lib/potassium/assets/config/puma.rb +1 -1
  32. data/lib/potassium/assets/config/shrine.rb +4 -1
  33. data/lib/potassium/assets/redis.yml +1 -2
  34. data/lib/potassium/assets/testing/rails_helper.rb +2 -0
  35. data/lib/potassium/cli/commands/create.rb +11 -19
  36. data/lib/potassium/cli_options.rb +70 -10
  37. data/lib/potassium/helpers/template-helpers.rb +4 -0
  38. data/lib/potassium/newest_version_ensurer.rb +19 -36
  39. data/lib/potassium/node_version_ensurer.rb +30 -0
  40. data/lib/potassium/recipes/admin.rb +26 -16
  41. data/lib/potassium/recipes/api.rb +92 -27
  42. data/lib/potassium/recipes/background_processor.rb +62 -18
  43. data/lib/potassium/recipes/ci.rb +9 -39
  44. data/lib/potassium/recipes/database.rb +4 -0
  45. data/lib/potassium/recipes/draper.rb +0 -9
  46. data/lib/potassium/recipes/file_storage.rb +2 -1
  47. data/lib/potassium/recipes/front_end.rb +84 -9
  48. data/lib/potassium/recipes/github.rb +93 -15
  49. data/lib/potassium/recipes/google_tag_manager.rb +94 -0
  50. data/lib/potassium/recipes/heroku.rb +42 -29
  51. data/lib/potassium/recipes/mailer.rb +18 -5
  52. data/lib/potassium/recipes/monitoring.rb +5 -0
  53. data/lib/potassium/recipes/schedule.rb +16 -1
  54. data/lib/potassium/recipes/style.rb +2 -2
  55. data/lib/potassium/templates/application.rb +5 -2
  56. data/lib/potassium/version.rb +5 -2
  57. data/potassium.gemspec +5 -2
  58. data/spec/features/api_spec.rb +25 -0
  59. data/spec/features/background_processor_spec.rb +19 -6
  60. data/spec/features/ci_spec.rb +7 -4
  61. data/spec/features/draper_spec.rb +1 -6
  62. data/spec/features/file_storage_spec.rb +5 -0
  63. data/spec/features/front_end_spec.rb +32 -1
  64. data/spec/features/github_spec.rb +53 -8
  65. data/spec/features/google_tag_manager_spec.rb +36 -0
  66. data/spec/features/graphql_spec.rb +71 -0
  67. data/spec/features/mailer_spec.rb +16 -0
  68. data/spec/features/schedule_spec.rb +11 -4
  69. data/spec/spec_helper.rb +1 -0
  70. data/spec/support/fake_octokit.rb +31 -0
  71. data/spec/support/potassium_test_helpers.rb +0 -1
  72. data/tmp/.keep +0 -0
  73. metadata +80 -15
  74. data/lib/potassium/assets/Dockerfile.ci +0 -6
  75. data/lib/potassium/assets/api/api_error_concern.rb +0 -32
  76. data/lib/potassium/assets/api/base_controller.rb +0 -7
  77. data/lib/potassium/assets/api/draper_responder.rb +0 -62
  78. data/lib/potassium/assets/api/responder.rb +0 -41
  79. data/lib/potassium/assets/bin/cibuild.erb +0 -117
  80. data/lib/potassium/assets/docker-compose.ci.yml +0 -12
  81. data/lib/potassium/assets/sidekiq_scheduler.yml +0 -9
@@ -24,11 +24,7 @@ class Recipes::Mailer < Rails::AppBuilder
24
24
  dependencies(email_service)
25
25
  config(email_service)
26
26
 
27
- background_processor_recipe = load_recipe(:background_processor)
28
- background_processor_answer = get(:background_processor)
29
-
30
- background_processor_recipe.add_sidekiq unless background_processor_recipe.installed? ||
31
- background_processor_answer
27
+ ensure_sidekiq_install_and_add_mailers_queue
32
28
  end
33
29
 
34
30
  def install
@@ -36,6 +32,10 @@ class Recipes::Mailer < Rails::AppBuilder
36
32
  create
37
33
  end
38
34
 
35
+ def add_mailer_queue
36
+ insert_into_file "config/sidekiq.yml", " - mailers", after: "- default\n"
37
+ end
38
+
39
39
  private
40
40
 
41
41
  def email_services(service_name)
@@ -102,4 +102,17 @@ class Recipes::Mailer < Rails::AppBuilder
102
102
  gather_gems(:development) { gather_gem("letter_opener") }
103
103
  application "config.action_mailer.delivery_method = :letter_opener", env: "development"
104
104
  end
105
+
106
+ def ensure_sidekiq_install_and_add_mailers_queue
107
+ background_processor_recipe = load_recipe(:background_processor)
108
+ background_processor_answer = get(:background_processor)
109
+
110
+ if background_processor_recipe.installed?
111
+ add_mailer_queue
112
+ else
113
+ recipe = self
114
+ after(:install_sidekiq) { recipe.add_mailer_queue }
115
+ background_processor_recipe.add_sidekiq unless background_processor_answer
116
+ end
117
+ end
105
118
  end
@@ -0,0 +1,5 @@
1
+ class Recipes::Monitoring < Rails::AppBuilder
2
+ def create
3
+ gather_gem('scout_apm')
4
+ end
5
+ end
@@ -10,8 +10,8 @@ class Recipes::Schedule < Rails::AppBuilder
10
10
  if selected?(:schedule)
11
11
  gather_gem 'sidekiq-scheduler', '>= 3.0.1'
12
12
  add_readme_section :internal_dependencies, :sidekiq_scheduler
13
+ append_schedule_section_to_yml
13
14
  end
14
- template '../assets/sidekiq_scheduler.yml', 'config/sidekiq.yml', force: true
15
15
  end
16
16
 
17
17
  def install
@@ -22,4 +22,19 @@ class Recipes::Schedule < Rails::AppBuilder
22
22
  def installed?
23
23
  gem_exists?(/sidekiq-scheduler/) && file_exist?('config/sidekiq.yml')
24
24
  end
25
+
26
+ private
27
+
28
+ def append_schedule_section_to_yml
29
+ append_to_file(
30
+ 'config/sidekiq.yml',
31
+ <<-HERE.gsub(/^ {8}/, '')
32
+ # :schedule:
33
+ # an_scheduled_task:
34
+ # cron: '0 * * * * *' # Runs once per minute
35
+ # class: ExampleJob
36
+ # args: ['a', 'b']
37
+ HERE
38
+ )
39
+ end
25
40
  end
@@ -13,10 +13,10 @@ class Recipes::Style < Rails::AppBuilder
13
13
 
14
14
  def add_linters
15
15
  gather_gems(:development, :test) do
16
- gather_gem 'rubocop', '~> 0.82.0'
16
+ gather_gem 'rubocop', Potassium::RUBOCOP_VERSION
17
17
  gather_gem 'rubocop-performance'
18
18
  gather_gem 'rubocop-rails'
19
- gather_gem 'rubocop-rspec'
19
+ gather_gem 'rubocop-rspec', Potassium::RUBOCOP_RSPEC_VERSION
20
20
  end
21
21
  run 'bin/yarn add --dev stylelint eslint eslint-plugin-import'
22
22
  run 'bin/yarn add --dev eslint-plugin-vue' if selected?(:front_end, :vue)
@@ -20,6 +20,7 @@ run_action(:asking) do
20
20
  ask :database
21
21
  ask :devise
22
22
  ask :admin
23
+ ask :google_tag_manager
23
24
  ask :front_end
24
25
  ask :vue_admin
25
26
  ask :mailer
@@ -58,9 +59,8 @@ run_action(:recipe_loading) do
58
59
  create :i18n
59
60
  create :pry
60
61
  create :better_errors
62
+ create :monitoring
61
63
  create :devise
62
- create :admin
63
- create :vue_admin
64
64
  create :seeds
65
65
  create :error_reporting
66
66
  create :pundit
@@ -76,6 +76,9 @@ run_action(:recipe_loading) do
76
76
  create :github
77
77
  create :cleanup
78
78
  create :front_end
79
+ create :admin
80
+ create :vue_admin
81
+ create :google_tag_manager
79
82
  end
80
83
 
81
84
  info "Gathered enough information. Applying the template. Wait a minute."
@@ -1,9 +1,12 @@
1
1
  module Potassium
2
- VERSION = "6.0.0"
2
+ VERSION = "6.4.0"
3
3
  RUBY_VERSION = "2.7.0"
4
4
  RAILS_VERSION = "~> 6.0.2"
5
- RUBOCOP_VERSION = "~> 0.65.0"
5
+ RUBOCOP_VERSION = "~> 1.9"
6
+ RUBOCOP_RSPEC_VERSION = "~> 2.2"
6
7
  POSTGRES_VERSION = "11.3"
7
8
  MYSQL_VERSION = "5.7"
8
9
  NODE_VERSION = "12"
10
+ TAILWINDCSS = "npm:@tailwindcss/postcss7-compat"
11
+ VUE_LOADER_VERSION = "^15.9.7"
9
12
  end
data/potassium.gemspec CHANGED
@@ -20,15 +20,18 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 2.0"
22
22
  spec.add_development_dependency "pry", "~> 0.10.3"
23
- spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rake", "~> 13.0"
24
24
  spec.add_development_dependency "rspec", "~> 3.4.0"
25
25
  spec.add_development_dependency "rspec_junit_formatter"
26
26
  spec.add_development_dependency "rubocop", Potassium::RUBOCOP_VERSION
27
- spec.add_development_dependency "rubocop-rspec"
27
+ spec.add_development_dependency "rubocop-performance"
28
+ spec.add_development_dependency "rubocop-rails"
29
+ spec.add_development_dependency "rubocop-rspec", Potassium::RUBOCOP_RSPEC_VERSION
28
30
  spec.add_runtime_dependency "gems", "~> 0.8"
29
31
  spec.add_runtime_dependency "gli", "~> 2.12.2"
30
32
  spec.add_runtime_dependency "inquirer", "~> 0.2"
31
33
  spec.add_runtime_dependency "levenshtein", "~> 0.2"
34
+ spec.add_runtime_dependency "octokit", "~> 4.18"
32
35
  spec.add_runtime_dependency "rails", Potassium::RAILS_VERSION
33
36
  spec.add_runtime_dependency "semantic", "~> 1.4"
34
37
  end
@@ -0,0 +1,25 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "Api" do
4
+ before :all do
5
+ drop_dummy_database
6
+ remove_project_directory
7
+ create_dummy_project("api" => :rest)
8
+ end
9
+
10
+ it "adds power_api related gems to Gemfile" do
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'")
14
+ end
15
+
16
+ it "adds the power_api brief to README file" do
17
+ readme = IO.read("#{project_path}/README.md")
18
+ expect(readme).to include("Power API")
19
+ end
20
+
21
+ it "installs power_api" do
22
+ content = IO.read("#{project_path}/app/controllers/api/base_controller.rb")
23
+ expect(content).to include("Api::BaseController < PowerApi::BaseController")
24
+ end
25
+ end
@@ -1,11 +1,12 @@
1
1
  require "spec_helper"
2
+ require 'yaml'
2
3
 
3
4
  RSpec.describe "BackgroundProcessor" do
4
- context "working with sidekiq" do
5
+ context "when working with sidekiq and no mailer" do
5
6
  before :all do
6
7
  drop_dummy_database
7
8
  remove_project_directory
8
- create_dummy_project("background_processor" => "sidekiq", "heroku" => true)
9
+ create_dummy_project("background_processor" => true, "heroku" => true)
9
10
  end
10
11
 
11
12
  it "adds sidekiq gem to Gemfile" do
@@ -41,6 +42,9 @@ RSpec.describe "BackgroundProcessor" do
41
42
  it "adds ENV vars" do
42
43
  content = IO.read("#{project_path}/.env.development")
43
44
  expect(content).to include("DB_POOL=25")
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)')
47
+ expect(content).to include('REDIS_URL=redis://${REDIS_HOST}:${REDIS_PORT}/1')
44
48
  end
45
49
 
46
50
  it "adds sidekiq.rb file" do
@@ -48,19 +52,28 @@ RSpec.describe "BackgroundProcessor" do
48
52
  expect(content).to include("require 'sidekiq'")
49
53
  end
50
54
 
51
- it "adds sidekiq.yml file" do
52
- content = IO.read("#{project_path}/config/sidekiq.yml")
53
- expect(content).to include("concurrency: 5")
55
+ it "adds sidekiq.yml file with no mailer queue" do
56
+ yml_path = "#{project_path}/config/sidekiq.yml"
57
+ content = IO.read(yml_path)
58
+ expect(File.exist?(yml_path)).to be true
59
+ expect(content).not_to include("- mailers")
54
60
  end
55
61
 
56
62
  it "adds redis.yml file" do
57
63
  content = IO.read("#{project_path}/config/redis.yml")
58
- expect(content).to include("REDIS_HOST")
64
+ expect(content).to include("REDIS_URL")
59
65
  end
60
66
 
61
67
  it "mounts sidekiq app" do
62
68
  content = IO.read("#{project_path}/config/routes.rb")
63
69
  expect(content).to include("mount Sidekiq::Web => '/queue'")
64
70
  end
71
+
72
+ it 'adds redis to docker-compose' do
73
+ compose_file = IO.read("#{project_path}/docker-compose.yml")
74
+ compose_content = YAML.safe_load(compose_file, symbolize_names: true)
75
+
76
+ expect(compose_content[:services]).to include(:redis)
77
+ end
65
78
  end
66
79
  end
@@ -1,14 +1,17 @@
1
1
  require "spec_helper"
2
2
  require "rubocop"
3
3
 
4
- RSpec.describe "A new project" do
4
+ RSpec.describe 'CI' do
5
5
  before(:all) do
6
6
  drop_dummy_database
7
7
  remove_project_directory
8
- create_dummy_project("heroku" => true)
8
+ create_dummy_project
9
9
  end
10
10
 
11
- it "correctly runs continous integration" do
12
- expect { on_project { `bin/cibuild` } }.to_not output.to_stderr
11
+ 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('circleci/ruby', 'cache', 'rspec', 'reviewdog')
13
16
  end
14
17
  end
@@ -4,7 +4,7 @@ RSpec.describe "Draper" do
4
4
  before :all do
5
5
  drop_dummy_database
6
6
  remove_project_directory
7
- create_dummy_project("draper" => true, "api" => true)
7
+ create_dummy_project("draper" => true)
8
8
  end
9
9
 
10
10
  it "adds the Draper gem to Gemfile" do
@@ -17,11 +17,6 @@ RSpec.describe "Draper" do
17
17
  expect(readme).to include("Draper")
18
18
  end
19
19
 
20
- it "adds api responder to work with draper" do
21
- responder_content = IO.read("#{project_path}/app/responders/api_responder.rb")
22
- expect(responder_content).to include("decorated_resource")
23
- end
24
-
25
20
  it "adds decorators directory" do
26
21
  content = IO.read("#{project_path}/app/decorators/.keep")
27
22
  expect(content).to be_empty
@@ -66,5 +66,10 @@ RSpec.describe "File Storage" do
66
66
  content = IO.read("#{project_path}/.env.development")
67
67
  expect(content).to include("S3_BUCKET=")
68
68
  end
69
+
70
+ it "adds filestorage path to gitignore" do
71
+ content = IO.read("#{project_path}/.gitignore")
72
+ expect(content).to include("/public/uploads")
73
+ end
69
74
  end
70
75
  end
@@ -19,7 +19,12 @@ RSpec.describe "Front end" do
19
19
  remove_project_directory
20
20
  create_dummy_project("front_end" => "None")
21
21
  expect(gemfile).to include('webpacker')
22
- expect(File).not_to exist(application_css_path)
22
+ end
23
+
24
+ def expect_to_have_tailwind_compatibility_build
25
+ expect(node_modules_file).to include("\"tailwindcss\": \"npm:@tailwindcss/postcss7-compat\"")
26
+ expect(node_modules_file).to include("\"autoprefixer\": \"^9\"")
27
+ expect(node_modules_file).to include("\"postcss\": \"^7\"")
23
28
  end
24
29
 
25
30
  context "with vue" do
@@ -54,6 +59,28 @@ RSpec.describe "Front end" do
54
59
  )
55
60
  expect(tailwind_config_file).to include('module.exports')
56
61
  end
62
+
63
+ it 'includes correct packages for tailwind, postcss and autoprefixer compatibility build' do
64
+ expect_to_have_tailwind_compatibility_build
65
+ end
66
+
67
+ it 'includes correct version of vue-loader in package' do
68
+ expect(node_modules_file).to include("\"vue-loader\": \"#{Potassium::VUE_LOADER_VERSION}\"")
69
+ end
70
+
71
+ context "with graphql" do
72
+ before(:all) do
73
+ remove_project_directory
74
+ create_dummy_project("front_end" => "vue", "api" => "graphql")
75
+ end
76
+
77
+ it "creates a vue project with apollo" do
78
+ expect(node_modules_file).to include("\"vue-apollo\"")
79
+ expect(application_js_file).to include("import { ApolloClient } from 'apollo-client';")
80
+ expect(application_js_file).to include("Vue.use(VueApollo)")
81
+ expect(application_js_file).to include("apolloProvider,")
82
+ end
83
+ end
57
84
  end
58
85
 
59
86
  context "with angular" do
@@ -70,5 +97,9 @@ RSpec.describe "Front end" do
70
97
  it "creates application_js_file for tailwind without vue" do
71
98
  expect(application_js_file).to include("import '../css/application.css';")
72
99
  end
100
+
101
+ it 'includes correct packages for tailwind, postcss and autoprefixer compatibility build' do
102
+ expect_to_have_tailwind_compatibility_build
103
+ end
73
104
  end
74
105
  end
@@ -1,22 +1,67 @@
1
1
  require "spec_helper"
2
2
 
3
3
  RSpec.describe "GitHub" do
4
+ let(:org_name) { "platanus" }
5
+ let(:repo_name) { PotassiumTestHelpers::APP_NAME.dasherize }
6
+ let(:access_token) { "1234" }
7
+ let(:pr_template_file) { IO.read("#{project_path}/.github/pull_request_template.md") }
8
+
4
9
  before do
5
10
  drop_dummy_database
6
11
  remove_project_directory
7
12
  end
8
13
 
9
- it "create a the github repository" do
10
- create_dummy_project("github" => true)
11
- app_name = PotassiumTestHelpers::APP_NAME.dasherize
14
+ it "creates the github repository" do
15
+ create_dummy_project(
16
+ "github" => true,
17
+ "github_private" => false,
18
+ "github_has_org" => false,
19
+ "github_name" => repo_name,
20
+ "github_access_token" => access_token
21
+ )
22
+
23
+ expect(FakeOctokit).to have_created_repo(repo_name)
24
+ expect(pr_template_file).to include('Contexto')
25
+ end
26
+
27
+ it "creates the private github repository" do
28
+ create_dummy_project(
29
+ "github" => true,
30
+ "github_private" => true,
31
+ "github_has_org" => false,
32
+ "github_name" => repo_name,
33
+ "github_access_token" => access_token
34
+ )
35
+
36
+ expect(FakeOctokit).to have_created_private_repo(repo_name)
37
+ expect(pr_template_file).to include('Contexto')
38
+ end
39
+
40
+ it "creates the github repository for the organization" do
41
+ create_dummy_project(
42
+ "github" => true,
43
+ "github_private" => false,
44
+ "github_has_org" => true,
45
+ "github_org" => org_name,
46
+ "github_name" => repo_name,
47
+ "github_access_token" => access_token
48
+ )
12
49
 
13
- expect(FakeGithub).to have_created_repo("platanus/#{app_name}")
50
+ expect(FakeOctokit).to have_created_repo_for_org(repo_name, org_name)
51
+ expect(pr_template_file).to include('Contexto')
14
52
  end
15
53
 
16
- it "create a the github private repository" do
17
- create_dummy_project("github" => true, "github-private" => true)
18
- app_name = PotassiumTestHelpers::APP_NAME.dasherize
54
+ it "creates the private github repository for the organization" do
55
+ create_dummy_project(
56
+ "github" => true,
57
+ "github_private" => true,
58
+ "github_has_org" => true,
59
+ "github_org" => org_name,
60
+ "github_name" => repo_name,
61
+ "github_access_token" => access_token
62
+ )
19
63
 
20
- expect(FakeGithub).to have_created_private_repo("platanus/#{app_name}")
64
+ expect(FakeOctokit).to have_created_private_repo_for_org(repo_name, org_name)
65
+ expect(pr_template_file).to include('Contexto')
21
66
  end
22
67
  end
@@ -0,0 +1,36 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "Google Tag Manager" do
4
+ before :all do
5
+ remove_project_directory
6
+ create_dummy_project('google_tag_manager' => true)
7
+ end
8
+
9
+ let(:gtm_head_file_path) do
10
+ "#{project_path}/app/views/shared/_gtm_head.html.erb"
11
+ end
12
+ let(:gtm_body_file_path) do
13
+ "#{project_path}/app/views/shared/_gtm_body.html.erb"
14
+ end
15
+ let(:content_security_policy_file_path) do
16
+ "#{project_path}/config/initializers/content_security_policy.rb"
17
+ end
18
+ let(:application_layout_file) do
19
+ IO.read("#{project_path}/app/views/layouts/application.html.erb")
20
+ end
21
+ let(:content_security_policy_file) do
22
+ IO.read(content_security_policy_file_path)
23
+ end
24
+
25
+ it 'adds google tag manager script' do
26
+ expect(File).to be_file(gtm_head_file_path)
27
+ expect(File).to be_file(gtm_body_file_path)
28
+ expect(application_layout_file).to include('shared/gtm_head')
29
+ expect(application_layout_file).to include('shared/gtm_body')
30
+ end
31
+
32
+ it 'add content security policy' do
33
+ expect(content_security_policy_file)
34
+ .to include("\nRails.application.config.content_security_policy do |policy|")
35
+ end
36
+ end