potassium 6.3.0 → 6.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +1 -1
  3. data/.node-version +1 -1
  4. data/CHANGELOG.md +45 -0
  5. data/README.md +30 -3
  6. data/docs/CONTRIBUTING.md +2 -2
  7. data/lib/potassium/assets/.circleci/config.yml.erb +40 -12
  8. data/lib/potassium/assets/.eslintrc.json +15 -9
  9. data/lib/potassium/assets/.pryrc +0 -6
  10. data/lib/potassium/assets/.rubocop.yml +1 -0
  11. data/lib/potassium/assets/Aptfile +5 -0
  12. data/lib/potassium/assets/README.yml +74 -7
  13. data/lib/potassium/assets/active_admin/admin-component.vue +22 -30
  14. data/lib/potassium/assets/active_admin/policies/admin_user_policy.rb +2 -0
  15. data/lib/potassium/assets/active_admin/policies/comment_policy.rb +2 -0
  16. data/lib/potassium/assets/active_admin/policies/default_policy.rb +49 -0
  17. data/lib/potassium/assets/active_admin/policies/page_policy.rb +2 -0
  18. data/lib/potassium/assets/app/javascript/{app.spec.js → components/app.spec.ts} +2 -2
  19. data/lib/potassium/assets/app/javascript/components/app.vue +9 -0
  20. data/lib/potassium/assets/app/javascript/types/vue.d.ts +5 -0
  21. data/lib/potassium/assets/app/jobs/shrine_promote_job.rb +14 -0
  22. data/lib/potassium/assets/app/mailers/application_mailer.rb +1 -1
  23. data/lib/potassium/assets/app/mailers/example_mailer.rb +6 -0
  24. data/lib/potassium/assets/app/serializers/base_serializer.rb +3 -0
  25. data/lib/potassium/assets/app/serializers/concerns/image_handling_attributes.rb +20 -0
  26. data/lib/potassium/assets/app/uploaders/cover_image_uploader.rb +52 -0
  27. data/lib/potassium/assets/app/views/example_mailer/example_mail.html.mjml +7 -0
  28. data/lib/potassium/assets/app/views/layouts/default_mail.html.mjml +49 -0
  29. data/lib/potassium/assets/config/initializers/shrine/plugins/image_handling_utilities.rb +143 -0
  30. data/lib/potassium/assets/config/mailer.rb.erb +0 -2
  31. data/lib/potassium/assets/config/shrine.rb +15 -0
  32. data/lib/potassium/assets/config/webpack/rules/css.js +5 -0
  33. data/lib/potassium/assets/config/webpack/rules/index.js +11 -0
  34. data/lib/potassium/assets/config/webpack/rules/jquery.js +11 -0
  35. data/lib/potassium/assets/config/webpack/rules/typescript.js +32 -0
  36. data/lib/potassium/assets/config/webpack/rules/vue.js +19 -0
  37. data/lib/potassium/assets/config/webpack/webpack.config.js +4 -0
  38. data/lib/potassium/assets/public/mails/platanus-logo.png +0 -0
  39. data/lib/potassium/assets/testing/.rspec +1 -0
  40. data/lib/potassium/assets/testing/devise_config.rb +6 -0
  41. data/lib/potassium/assets/testing/factory_bot_config.rb +3 -0
  42. data/lib/potassium/assets/testing/faker_config.rb +1 -0
  43. data/lib/potassium/assets/testing/power_types_config.rb +1 -0
  44. data/lib/potassium/assets/testing/rails_helper.rb +130 -49
  45. data/lib/potassium/assets/testing/shoulda_matchers_config.rb +8 -0
  46. data/lib/potassium/assets/testing/simplecov_config.rb +64 -0
  47. data/lib/potassium/assets/testing/system_tests_config.rb +6 -0
  48. data/lib/potassium/assets/tsconfig.json +31 -0
  49. data/lib/potassium/cli/commands/create.rb +3 -1
  50. data/lib/potassium/cli_options.rb +23 -3
  51. data/lib/potassium/platanus_config.rb +20 -0
  52. data/lib/potassium/recipes/admin.rb +37 -16
  53. data/lib/potassium/recipes/api.rb +8 -85
  54. data/lib/potassium/recipes/coverage.rb +66 -0
  55. data/lib/potassium/recipes/file_storage.rb +50 -0
  56. data/lib/potassium/recipes/front_end.rb +87 -108
  57. data/lib/potassium/recipes/google_tag_manager.rb +20 -16
  58. data/lib/potassium/recipes/heroku.rb +1 -2
  59. data/lib/potassium/recipes/mailer.rb +22 -10
  60. data/lib/potassium/recipes/mjml.rb +31 -0
  61. data/lib/potassium/recipes/node.rb +11 -13
  62. data/lib/potassium/recipes/pundit.rb +29 -10
  63. data/lib/potassium/recipes/rails.rb +0 -4
  64. data/lib/potassium/recipes/spring.rb +9 -0
  65. data/lib/potassium/recipes/style.rb +9 -2
  66. data/lib/potassium/recipes/testing.rb +75 -18
  67. data/lib/potassium/recipes/vue_admin.rb +38 -8
  68. data/lib/potassium/templates/application.rb +5 -2
  69. data/lib/potassium/version.rb +10 -4
  70. data/spec/features/api_spec.rb +6 -1
  71. data/spec/features/ci_spec.rb +1 -1
  72. data/spec/features/coverage_spec.rb +43 -0
  73. data/spec/features/file_storage_spec.rb +102 -26
  74. data/spec/features/front_end_spec.rb +16 -47
  75. data/spec/features/google_tag_manager_spec.rb +1 -24
  76. data/spec/features/heroku_spec.rb +0 -4
  77. data/spec/features/mailer_spec.rb +79 -33
  78. data/spec/features/mjml_spec.rb +53 -0
  79. data/spec/features/node_spec.rb +1 -1
  80. data/spec/features/pundit_spec.rb +34 -0
  81. data/spec/features/testing_spec.rb +56 -0
  82. data/spec/features/vue_admin_spec.rb +0 -10
  83. data/spec/support/potassium_test_helpers.rb +2 -2
  84. data/spec/support/shared_examples.rb +5 -0
  85. metadata +50 -27
  86. data/lib/potassium/assets/active_admin/admin_application.js +0 -14
  87. data/lib/potassium/assets/active_admin/admin_user_policy.rb +0 -2
  88. data/lib/potassium/assets/active_admin/comment_policy.rb +0 -2
  89. data/lib/potassium/assets/active_admin/init_activeadmin_vue.rb +0 -10
  90. data/lib/potassium/assets/active_admin/pundit_page_policy.rb +0 -5
  91. data/lib/potassium/assets/app/graphql/graphql_controller.rb +0 -55
  92. data/lib/potassium/assets/app/graphql/mutations/login_mutation.rb +0 -23
  93. data/lib/potassium/assets/app/graphql/queries/base_query.rb +0 -4
  94. data/lib/potassium/assets/app/graphql/types/base/base_argument.rb +0 -4
  95. data/lib/potassium/assets/app/graphql/types/base/base_enum.rb +0 -4
  96. data/lib/potassium/assets/app/graphql/types/base/base_field.rb +0 -5
  97. data/lib/potassium/assets/app/graphql/types/base/base_input_object.rb +0 -5
  98. data/lib/potassium/assets/app/graphql/types/base/base_interface.rb +0 -7
  99. data/lib/potassium/assets/app/graphql/types/base/base_object.rb +0 -5
  100. data/lib/potassium/assets/app/graphql/types/base/base_scalar.rb +0 -4
  101. data/lib/potassium/assets/app/graphql/types/base/base_union.rb +0 -4
  102. data/lib/potassium/assets/app/graphql/types/mutation_type.rb +0 -10
  103. data/lib/potassium/assets/app/graphql/types/query_type.rb +0 -13
  104. data/lib/potassium/assets/config/graphql_playground.rb +0 -20
  105. data/spec/features/graphql_spec.rb +0 -71
@@ -0,0 +1,3 @@
1
+ class BaseSerializer < ActiveModel::Serializer
2
+ include ImageHandlingAttributes
3
+ end
@@ -0,0 +1,20 @@
1
+ module ImageHandlingAttributes
2
+ extend ActiveSupport::Concern
3
+
4
+ class_methods do
5
+ def add_image_handling_attributes(attachment_name:, derivatives:, include_original_image: false)
6
+ attributes attachment_name, "#{attachment_name}_blurhash".to_sym
7
+
8
+ define_method(attachment_name) do
9
+ attachment_hash = derivatives.reduce({}) do |hash, derivative|
10
+ hash[derivative] = { url: object.send("#{attachment_name}_url", derivative) }
11
+ hash
12
+ end
13
+ if include_original_image
14
+ attachment_hash[:original] = { url: object.send("#{attachment_name}_url") }
15
+ end
16
+ attachment_hash
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,52 @@
1
+ require "image_processing/vips"
2
+
3
+ class CoverImageUploader < ImageUploader
4
+ plugin :derivation_endpoint, prefix: "derivations/cover_image"
5
+ plugin :add_metadata
6
+ plugin :image_handling_utilities
7
+
8
+ DERIVATIVES = {
9
+ sm: { size: [426, 240], type: 'jpg' },
10
+ md: { size: [960, 540], type: 'jpg' },
11
+ lg: { size: [1280, 720], type: 'jpg' },
12
+ webp_sm: { size: [426, 240], type: 'webp' },
13
+ webp_md: { size: [960, 540], type: 'webp' },
14
+ webp_lg: { size: [1280, 720], type: 'webp' }
15
+ }
16
+
17
+ Attacher.derivatives do |original|
18
+ vips = ImageProcessing::Vips.source(original)
19
+
20
+ DERIVATIVES.reduce({}) do |derivatives_hash, (name, derivative_info)|
21
+ derivatives_hash[name] = vips.convert(derivative_info[:type]).resize_to_limit!(
22
+ *derivative_info[:size]
23
+ )
24
+ derivatives_hash
25
+ end
26
+ end
27
+
28
+ derivation :thumbnail do |file, width, height|
29
+ ImageProcessing::Vips
30
+ .source(file)
31
+ .resize_to_limit!(width.to_i, height.to_i)
32
+ end
33
+
34
+ Attacher.default_url do |derivative: nil, **|
35
+ file&.derivation_url(:thumbnail, *DERIVATIVES.dig(derivative, :size)) if derivative.present?
36
+ end
37
+
38
+ add_metadata :blurhash do |io, derivative: nil, **|
39
+ if derivative.nil?
40
+ Shrine.with_file(io) do |file|
41
+ image = Vips::Image.new_from_file(file.path, access: :sequential)
42
+ image = image.resize(100.0 / image.width)
43
+ flat_rgb_pixels = []
44
+ image.to_a.each do |row|
45
+ row.each { |pixel| flat_rgb_pixels.concat(pixel[0..2]) }
46
+ end
47
+
48
+ Blurhash.encode(image.width, image.height, flat_rgb_pixels)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,7 @@
1
+ <mj-section>
2
+ <mj-column>
3
+ <mj-text>
4
+ Hello <%= @email %>, welcome to Potassium
5
+ </mj-text>
6
+ </mj-column>
7
+ </mj-section>
@@ -0,0 +1,49 @@
1
+ <mjml>
2
+ <mj-head>
3
+ <mj-attributes>
4
+ <mj-all font-family="'Helvetica Neue', Helvetica, Arial, sans-serif"></mj-all>
5
+ <mj-text font-weight="400" font-size="16px" color="#000000" line-height="24px" font-family="'Helvetica Neue', Helvetica, Arial, sans-serif"></mj-text>
6
+ </mj-attributes>
7
+ <mj-style inline="inline">
8
+ .body-section {
9
+ -webkit-box-shadow: 1px 4px 11px 0px rgba(0, 0, 0, 0.15);
10
+ -moz-box-shadow: 1px 4px 11px 0px rgba(0, 0, 0, 0.15);
11
+ box-shadow: 1px 4px 11px 0px rgba(0, 0, 0, 0.15);
12
+ }
13
+ </mj-style>
14
+ <mj-style inline="inline">
15
+ .text-link {
16
+ color: #5e6ebf
17
+ }
18
+ </mj-style>
19
+ <mj-style inline="inline">
20
+ .footer-link {
21
+ color: #888888
22
+ }
23
+ </mj-style>
24
+
25
+ </mj-head>
26
+ <mj-body width="600px">
27
+ <mj-section full-width="full-width" background-color="#71717A" padding-bottom="0">
28
+ <mj-column width="100%" background-color="#A1A1AA">
29
+ <mj-spacer height="25px" />
30
+ </mj-column>
31
+ </mj-section>
32
+ <mj-section background-color="#A1A1AA" padding-bottom="0" padding-top="0">
33
+ <mj-column>
34
+ <mj-image width="100px" src="<%= image_url('/mails/platanus-logo.png') %>" align="center">
35
+ </mj-column>
36
+ <mj-column width="100%">
37
+ <mj-spacer height="25px" />
38
+ </mj-column>
39
+ </mj-section>
40
+ <mj-wrapper padding-top="0" padding-bottom="0" css-class="body-section" background-color="#ffffff" padding-left="15px" padding-right="15px">
41
+ <%= yield %>
42
+ </mj-wrapper>
43
+ <mj-section background-color="#A1A1AA" padding-bottom="0" padding-top="0">
44
+ <mj-column width="100%">
45
+ <mj-spacer height="25px" />
46
+ </mj-column>
47
+ </mj-section>
48
+ </mj-body>
49
+ </mjml>
@@ -0,0 +1,143 @@
1
+ class Shrine
2
+ module Plugins
3
+ module ImageHandlingUtilities
4
+ # rubocop:disable Metrics/ModuleLength
5
+ module AttachmentMethods
6
+ def included(klass)
7
+ super
8
+
9
+ define_instance_methods
10
+ define_class_methods(klass)
11
+ end
12
+
13
+ private
14
+
15
+ def define_instance_methods
16
+ define_with_stored_attacher_method
17
+ define_blurhash_instance_method
18
+ define_generate_derivatives_instance_method
19
+ define_generate_metadata_instance_method
20
+ define_generate_derivatives_and_metadata_instance_method
21
+ end
22
+
23
+ def define_blurhash_instance_method
24
+ name = @name
25
+ define_method(:"#{@name}_blurhash") do
26
+ send(name)&.metadata&.[]('blurhash')
27
+ end
28
+ end
29
+
30
+ def define_generate_derivatives_instance_method
31
+ name = @name
32
+ define_method(:"generate_#{name}_derivatives") do
33
+ send("with_stored_#{name}_attacher") do |attacher|
34
+ old_derivatives = attacher.derivatives
35
+
36
+ attacher.set_derivatives({})
37
+ attacher.create_derivatives
38
+
39
+ begin
40
+ attacher.atomic_persist
41
+ attacher.delete_derivatives(old_derivatives) if old_derivatives.present?
42
+ rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound
43
+ attacher.delete_derivatives
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ def define_generate_metadata_instance_method
50
+ name = @name
51
+ define_method(:"generate_#{name}_metadata") do
52
+ send("with_stored_#{name}_attacher") do |attacher|
53
+ attacher.refresh_metadata!
54
+ attacher.atomic_persist
55
+ end
56
+ end
57
+ end
58
+
59
+ # rubocop:disable Metrics/MethodLength
60
+ def define_generate_derivatives_and_metadata_instance_method
61
+ name = @name
62
+ define_method(:"generate_#{name}_derivatives_and_metadata") do
63
+ send("with_stored_#{name}_attacher") do |attacher|
64
+ old_derivatives = attacher.derivatives
65
+
66
+ attacher.set_derivatives({})
67
+ attacher.file.open do
68
+ attacher.create_derivatives
69
+ attacher.refresh_metadata!
70
+ end
71
+
72
+ begin
73
+ attacher.atomic_persist
74
+ attacher.delete_derivatives(old_derivatives) if old_derivatives.present?
75
+ rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound
76
+ attacher.delete_derivatives
77
+ end
78
+ end
79
+ end
80
+ end
81
+ # rubocop:enable Metrics/MethodLength
82
+
83
+ def define_class_methods(klass)
84
+ define_generate_all_derivatives_class_method(klass)
85
+ define_generate_all_metadata_class_method(klass)
86
+ define_generate_all_derivatives_and_metadata_class_method(klass)
87
+ end
88
+
89
+ def define_generate_all_derivatives_class_method(klass)
90
+ name = @name
91
+ klass.send(
92
+ :define_singleton_method, :"generate_all_#{name}_derivatives"
93
+ ) do |&error_block|
94
+ all.find_each do |record|
95
+ record.send(:"generate_#{name}_derivatives")
96
+ rescue StandardError => e
97
+ error_block.call(record, e) if error_block.present?
98
+ end
99
+ end
100
+ end
101
+
102
+ def define_generate_all_metadata_class_method(klass)
103
+ name = @name
104
+ klass.send(:define_singleton_method, :"generate_all_#{name}_metadata") do |&error_block|
105
+ all.find_each do |record|
106
+ record.send(:"generate_#{name}_metadata")
107
+ rescue StandardError => e
108
+ error_block.call(record, e) if error_block.present?
109
+ end
110
+ end
111
+ end
112
+
113
+ def define_generate_all_derivatives_and_metadata_class_method(klass)
114
+ name = @name
115
+ klass.send(
116
+ :define_singleton_method, :"generate_all_#{name}_derivatives_and_metadata"
117
+ ) do |&error_block|
118
+ all.find_each do |record|
119
+ record.send(:"generate_#{name}_derivatives_and_metadata")
120
+ rescue StandardError => e
121
+ error_block.call(record, e) if error_block.present?
122
+ end
123
+ end
124
+ end
125
+
126
+ def define_with_stored_attacher_method
127
+ name = @name
128
+ define_method(:"with_stored_#{name}_attacher") do |&block|
129
+ return if send(name).blank?
130
+
131
+ attacher = send(:"#{name}_attacher")
132
+
133
+ block.call(attacher) if attacher.stored?
134
+ end
135
+ private :"with_stored_#{name}_attacher"
136
+ end
137
+ end
138
+ # rubocop:enable Metrics/ModuleLength
139
+ end
140
+
141
+ register_plugin(:image_handling_utilities, ImageHandlingUtilities)
142
+ end
143
+ end
@@ -7,8 +7,6 @@ Rails.application.config.action_mailer.default_url_options = {
7
7
  }
8
8
 
9
9
  Rails.application.config.action_mailer.default_options = { from: ENV['DEFAULT_EMAIL_ADDRESS'] }
10
- ASSET_HOST = ENV.fetch("ASSET_HOST", ENV.fetch("APPLICATION_HOST"))
11
- Rails.application.config.action_mailer.asset_host = ASSET_HOST
12
10
 
13
11
  if ENV["EMAIL_RECIPIENTS"].present?
14
12
  Mail.register_interceptor RecipientInterceptor.new(
@@ -34,3 +34,18 @@ Shrine.plugin :activerecord
34
34
  Shrine.plugin :cached_attachment_data
35
35
  Shrine.plugin :restore_cached_data
36
36
  Shrine.plugin :determine_mime_type, analyzer: :marcel
37
+ Shrine.plugin :derivatives
38
+ Shrine.plugin :default_url
39
+ Shrine.plugin :derivation_endpoint, secret_key: ENV.fetch('SHRINE_SECRET_KEY')
40
+ Shrine.plugin :refresh_metadata
41
+ Shrine.plugin :backgrounding
42
+
43
+ Shrine::Attacher.promote_block do |attacher|
44
+ ShrinePromoteJob.perform_later(
45
+ attacher.class.name,
46
+ attacher.record.class.name,
47
+ attacher.record.id,
48
+ attacher.name,
49
+ attacher.file_data
50
+ )
51
+ end
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ resolve: {
3
+ extensions: ['.css', '.scss']
4
+ }
5
+ }
@@ -0,0 +1,11 @@
1
+ const vueConfig = require('./vue');
2
+ const cssConfig = require('./css');
3
+ const jQueryConfig = require('./jquery');
4
+ const typescriptConfig = require('./typescript');
5
+
6
+ module.exports = {
7
+ vueConfig,
8
+ cssConfig,
9
+ jQueryConfig,
10
+ typescriptConfig,
11
+ };
@@ -0,0 +1,11 @@
1
+ const webpack = require('webpack');
2
+
3
+ module.exports = {
4
+ plugins: [
5
+ new webpack.ProvidePlugin({
6
+ $: 'jquery',
7
+ jQuery: 'jquery',
8
+ "window.jQuery":"jquery"
9
+ })
10
+ ],
11
+ }
@@ -0,0 +1,32 @@
1
+ const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
2
+
3
+ module.exports = {
4
+ module: {
5
+ rules: [
6
+ {
7
+ test: /\.ts$/,
8
+ loader: 'ts-loader',
9
+ exclude: /node_modules/,
10
+ options: {
11
+ appendTsSuffixTo: [/\.vue$/],
12
+ transpileOnly: true,
13
+ },
14
+ },
15
+ ],
16
+ },
17
+ resolve: {
18
+ extensions: ['.ts'],
19
+ },
20
+ plugins: [
21
+ new ForkTsCheckerWebpackPlugin({
22
+ typescript: {
23
+ extensions: {
24
+ vue: {
25
+ enabled: true,
26
+ compiler: '@vue/compiler-sfc',
27
+ },
28
+ },
29
+ },
30
+ }),
31
+ ],
32
+ };
@@ -0,0 +1,19 @@
1
+ const { VueLoaderPlugin } = require('vue-loader')
2
+
3
+ module.exports = {
4
+ module: {
5
+ rules: [
6
+ {
7
+ test: /\.vue$/,
8
+ loader: 'vue-loader'
9
+ }
10
+ ]
11
+ },
12
+ plugins: [new VueLoaderPlugin()],
13
+ resolve: {
14
+ extensions: ['.vue'],
15
+ alias: {
16
+ 'vue$': 'vue/dist/vue.esm-bundler.js',
17
+ }
18
+ },
19
+ }
@@ -0,0 +1,4 @@
1
+ const { webpackConfig, merge } = require('shakapacker');
2
+ const { vueConfig, cssConfig, jQueryConfig, typescriptConfig } = require('./rules');
3
+
4
+ module.exports = merge(typescriptConfig, cssConfig, jQueryConfig, webpackConfig);
@@ -2,3 +2,4 @@
2
2
  --require rails_helper
3
3
  --format=doc
4
4
  --format=Nc
5
+ --tag ~type:system
@@ -0,0 +1,6 @@
1
+ require 'devise'
2
+
3
+ RSpec.configure do |config|
4
+ config.include Devise::Test::ControllerHelpers, type: :controller
5
+ config.include Devise::Test::IntegrationHelpers, type: :request
6
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.configure do |config|
2
+ config.include FactoryBot::Syntax::Methods
3
+ end
@@ -0,0 +1 @@
1
+ require 'faker'
@@ -0,0 +1 @@
1
+ PowerTypes::Observable.observable_disabled = true
@@ -1,60 +1,141 @@
1
- # This file is copied to spec/ when you run 'rails generate rspec:install'
2
1
  ENV['RACK_ENV'] ||= 'test'
3
2
  require File.expand_path('../config/environment', __dir__)
4
3
  require 'rspec/rails'
5
4
  require 'spec_helper'
6
- require 'shoulda/matchers'
7
- require 'faker'
8
- # Add additional requires below this line. Rails is not loaded until this point!
9
-
10
- # Requires supporting ruby files with custom matchers and macros, etc, in
11
- # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
12
- # run as spec files by default. This means that files in spec/support that end
13
- # in _spec.rb will both be required and run as specs, causing the specs to be
14
- # run twice. It is recommended that you do not name files matching this glob to
15
- # end with _spec.rb. You can configure this pattern with the --pattern
16
- # option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
17
- #
18
- # The following line is provided for convenience purposes. It has the downside
19
- # of increasing the boot-up time by auto-requiring all files in the support
20
- # directory. Alternatively, in the individual `*_spec.rb` files, manually
21
- # require only the support files necessary.
22
- #
23
- Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
24
-
25
- # Checks for pending migrations before tests are run.
26
- # If you are not using ActiveRecord, you can remove this line.
27
- ActiveRecord::Migration.maintain_test_schema!
28
5
 
29
- PowerTypes::Observable.observable_disabled = true
6
+ =begin
30
7
 
31
- RSpec.configure do |config|
32
- # If you're not using ActiveRecord, or you'd prefer not to run each of your
33
- # examples within a transaction, remove the following line or assign false
34
- # instead of true.
35
- config.use_transactional_fixtures = true
8
+ General
9
+ =======
36
10
 
37
- # RSpec Rails can automatically mix in different behaviours to your tests
38
- # based on their file location, for example enabling you to call `get` and
39
- # `post` in specs under `spec/controllers`.
40
- #
41
- # You can disable this behaviour by removing the line below, and instead
42
- # explicitly tag your specs with their type, e.g.:
43
- #
44
- # RSpec.describe UsersController, :type => :controller do
45
- # # ...
46
- # end
47
- #
48
- # The different available types are documented in the features, such as in
49
- # https://relishapp.com/rspec/rspec-rails/docs
50
- config.infer_spec_type_from_file_location!
11
+ 1) Place your unit tests inside the "spec" directory.
12
+ 2) Run unit tests executing `bin/guard`.
13
+ 3) Use support directories to add helpers and settings.
14
+ You can only put RSpec configuration on this file.
51
15
 
52
- config.include FactoryBot::Syntax::Methods
53
- end
16
+ Support
17
+ -------
18
+
19
+ * spec/support/configurations: put testing related gem settings here.
20
+
21
+ For example: spec/support/configurations/shoulda_matchers_config.rb
22
+
23
+ ----------------------------------------
24
+ require 'shoulda/matchers'
25
+
26
+ Shoulda::Matchers.configure do |config|
27
+ config.integrate do |with|
28
+ with.test_framework :rspec
29
+ with.library :rails
30
+ end
31
+ end
32
+ ----------------------------------------
33
+
34
+ * spec/support/helpers: place here helpers created by you to use in your unit tests.
35
+
36
+ For example: spec/support/helpers/attachments_helpers.rb
37
+
38
+ ----------------------------------------------------------------------------------
39
+ module AttachmentsHelpers
40
+ extend ActiveSupport::Concern
41
+
42
+ included do
43
+ def create_attachment_file(filename: "pikachu.png", content_type: "image/png")
44
+ Rack::Test::UploadedFile.new(file_fixture(filename), content_type)
45
+ end
46
+ end
47
+ end
48
+
49
+ RSpec.configure do |config|
50
+ config.fixture_path = "#{::Rails.root}/spec/assets"
51
+ config.file_fixture_path = "#{::Rails.root}/spec/assets"
52
+
53
+ config.include AttachmentsHelpers
54
+ end
55
+ ----------------------------------------------------------------------------------
56
+
57
+ * spec/support/custom_matchers: place here your custom matchers
58
+ (https://relishapp.com/rspec/rspec-expectations/v/3-10/docs/custom-matchers)
59
+
60
+ * spec/support/shared_examples: place here your shared examples
61
+ (https://relishapp.com/rspec/rspec-core/v/3-10/docs/example-groups/shared-examples)
62
+
63
+ System Tests
64
+ ============
65
+
66
+ 1) Place your system tests inside the "spec/system" directory.
67
+ 2) Run system tests executing `bin/rspec --tag type:system`.
68
+
69
+ Support
70
+ -------
71
+
72
+ * spec/support/configurations/system_tests_config.rb: on this file you will find the
73
+ general configuration of the system tests. Keep in mind that this type of test will
74
+ run with the `selenium_chrome_headless` driver unless you put the `no_js` tag.
54
75
 
55
- Shoulda::Matchers.configure do |config|
56
- config.integrate do |with|
57
- with.test_framework :rspec
58
- with.library :rails
76
+ For example: spec/system/login_spec.rb
77
+
78
+ ----------------------------------------------------------------------------
79
+ require "rails_helper"
80
+
81
+ RSpec.describe "Login" do
82
+ let!(:user) { create(:user, email: "lean@platan.us") }
83
+
84
+ context "without logged user", :no_js do # will use :rack_test driver
85
+ before { visit("/") }
86
+
87
+ it { expect(page).to have_text("Ingresa") }
88
+ end
89
+
90
+ context "with logged user" do # will use :selenium_chrome_headless driver
91
+ before { sign_in(user) }
92
+
93
+ it { expect(page).to have_text("Hola!") }
94
+ end
95
+ end
96
+ ----------------------------------------------------------------------------
97
+
98
+ * spec/support/helpers/system: place here helpers created by you
99
+ to use in your system tests.
100
+
101
+ For example: spec/support/helpers/login_helpers.rb
102
+
103
+ ------------------------------------------------
104
+ module LoginHelpers
105
+ extend ActiveSupport::Concern
106
+
107
+ included do
108
+ def sign_in(email, password)
109
+ visit('/users/sign_in')
110
+
111
+ within(:xpath, '//*[@id="new_user"]') do
112
+ fill_in('Email', with: email)
113
+ fill_in('Contraseña', with: password)
114
+ end
115
+
116
+ click_button('Ingresar')
117
+ end
118
+
119
+ def logout
120
+ visit('/users/sign_out')
121
+ end
122
+ end
123
+ end
124
+
125
+ RSpec.configure do |config|
126
+ config.include LoginHelpers, type: :system
59
127
  end
128
+ ------------------------------------------------
129
+
130
+ Remember to include the system helpers with the tag `type: :system`
131
+ =end
132
+
133
+ Dir[Rails.root.join("spec/support/**/*.rb")].sort.each { |f| require f }
134
+
135
+ ActiveRecord::Migration.maintain_test_schema!
136
+
137
+ RSpec.configure do |config|
138
+ config.use_transactional_fixtures = true
139
+ config.infer_spec_type_from_file_location!
140
+ config.filter_run_when_matching :focus unless Rails.env.production?
60
141
  end
@@ -0,0 +1,8 @@
1
+ require 'shoulda/matchers'
2
+
3
+ Shoulda::Matchers.configure do |config|
4
+ config.integrate do |with|
5
+ with.test_framework :rspec
6
+ with.library :rails
7
+ end
8
+ end